diff -r 6297cdf66332 -r d39add9822e2 webengine/webkitutils/stmgesturefw/src/stmgestureinterface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/webkitutils/stmgesturefw/src/stmgestureinterface.cpp Tue Feb 02 00:56:45 2010 +0200 @@ -0,0 +1,618 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: Gesture helper implementation +* +*/ + + +// Gesture UI Engine +#include "statemachine.h" + +// Gesture Library: Framework +#include "gestureframework.h" +#include "rt_gestureengineif.h" + +// Gesture Library: Recognizers +#include "tapgesturerecogniser.h" +#include "pangesturerecogniser.h" +#include "edgescrollgesturerecogniser.h" +#include "longpressgesturerecogniser.h" +#include "pinchgesturerecogniser.h" +#include "touchgesturerecogniser.h" +#include "releasegesturerecogniser.h" +#include "flickgesturerecogniser.h" +#include "zoomgesturerecogniser.h" + +#include "stmgestureinterface.h" +#include "gesturehelpereventsender.h" + +#ifndef ICS_DCHECK +#define ICS_DCHECK(test) +#endif + +#define LOG(args...) + + +EXPORT_C CStmGestureParameters::CStmGestureParameters() + { + + } + +EXPORT_C CStmGestureParameters::CStmGestureParameters( + const CStmGestureParameters& aParams ) + { + Mem::Copy(&iParam[0], &aParams.iParam[0], sizeof(iParam)); + Mem::Copy(&iAreaSettings[0], &aParams.iAreaSettings[0], sizeof(iAreaSettings)); + Mem::Copy(&iEnabled[0], &aParams.iEnabled[0], sizeof(iEnabled)); + } + +EXPORT_C CStmGestureEngine* CStmGestureEngine::NewL() + { + CStmGestureEngine* eng = new(ELeave) CStmGestureEngine(); + CleanupStack::PushL(eng); + eng->ConstructL(); + CleanupStack::Pop(eng); + return eng; + } + +CStmGestureEngine::CStmGestureEngine() + { + + } + +void CStmGestureEngine::ConstructL() + { + iGf = stmGesture::CGestureFramework::NewL(); + } + +CStmGestureEngine::~CStmGestureEngine() + { + // Prevent reactivation of contexts as they remove themselves + iDtorPhase = ETrue; + + iContexts.ResetAndDestroy(); + iCtxtStack.Reset(); + delete iGf; + } + +EXPORT_C CStmGestureContext* CStmGestureEngine::CreateContextL( + TInt /*aId*/ ) + { + CStmGestureContext* ctxt = new(ELeave) CStmGestureContext(*this); + CleanupStack::PushL(ctxt); + ctxt->ConstructL(); + CleanupStack::Pop(ctxt); + return ctxt; + } + +EXPORT_C CStmGestureContext* CStmGestureEngine::Context( + TInt /*aId*/ ) + { + return NULL; + } + +void CStmGestureEngine::EnableContextL( + CStmGestureContext& aContext ) + { + // NB: enabling context puts it on top of the Context Stack + TInt idx = iCtxtStack.Find(&aContext); + if(idx >= 0) + { + iCtxtStack.Remove(idx); + } + + SetupRecognizersL(aContext, ETrue); + + iCtxtStack.AppendL(&aContext); + } + +void CStmGestureEngine::DisableContextL( + CStmGestureContext& aContext ) + { + TInt idx = iCtxtStack.Find(&aContext); + ICS_DCHECK(idx >= 0); + if(idx == KErrNotFound) + { + return; + } + + iCtxtStack.Remove(idx); + + stmGesture::MGestureEngineIf* ge = iGf->getGestureEngine(); + + for(TInt i = 0; i < stmGesture::EStmGestureUid_Count; ++i) + { + MStmGestureRecogniser* rec = aContext.iRecognizers[i]; + if(rec) + { + ge->removeGesture(rec); + } + } + + // re-activate previous (new top-most) context + // NB: if deleted context is not top-most (active) one, no updates done + TInt count = iCtxtStack.Count(); + if(idx == count && count > 0 && !iDtorPhase) + { + CStmGestureContext* previous = iCtxtStack[count - 1]; + SetupRecognizersL(*previous, EFalse); + } + } + +template +void CStmGestureEngine::InitRecognizerL( + T*& aGesture, + CStmGestureContext& aContext, + TBool aNewContext ) + { + stmGesture::MGestureRecogniserIf*& recognizer = aContext.iRecognizers[T::KUid]; + aGesture = static_cast(recognizer); + if(!aGesture && aNewContext) + { + recognizer = aGesture = T::NewL(&aContext); + recognizer->enableLogging((aContext.iLogging & (1<getGestureEngine()->addGesture(aGesture); + if(!added) + { + User::Leave(KErrNoMemory); + } + } + +void CStmGestureEngine::SetupRecognizersL( + CStmGestureContext& aContext, + TBool aNewContext ) + { + LOG("Setup recognizers"); + // Order of recognizers in the Gesture Engine (upper ones receive input before lower ones) + // + // PINCH + // CORNER_ZOOM + // EDGE_SCROLL + // LONGPRESS + // TOUCH + // UP_DOWN + // LEFT_RIGHT + // HOVER + // PAN + // TAP / DOUBLE_TAP + // FLICK + // RELEASE + // UNKNOWN + + stmUiEventEngine::CStateMachine* stateMachine = iGf->getUiStateMachine(); + stmGesture::MGestureEngineIf* gestureEngine = iGf->getGestureEngine(); + + MStmGestureParameters& conf = aContext.Config(); + + TBool filter = conf.Param(stmGesture::EEnableFiltering) != 0; + + // TOUCH AREA + TStmGestureArea& touchArea = *conf.Area(stmGesture::ETouchArea); + TInt touchAreaSizeInMm = touchArea.iSize.iWidth; + stateMachine->setTouchAreaShape ( stmUiEventEngine::TAreaShape(touchArea.iShape) ); + stateMachine->setTouchArea ( !filter ? 0 : touchAreaSizeInMm ); + stateMachine->setTouchTimeout ( !filter ? 0 : touchArea.iTimeout * 1000); + CCoeControl* gestureContext = aContext.getOwner(); + TRect ctxtRect = gestureContext->Rect(); + + // ===================================================== PINCH + using stmGesture::CPinchGestureRecogniser; + + if (conf.Enabled(CPinchGestureRecogniser::KUid)) + { + CPinchGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + TReal32 pspeed = conf.Param(stmGesture::EPinchSpeed) / 1000.f; + gesture->setPinchingSpeed(pspeed); + } + } + + // ===================================================== LONG PRESS + using stmGesture::CLongPressGestureRecogniser; + + if (conf.Enabled(CLongPressGestureRecogniser::KUid)) + { + CLongPressGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setArea(ctxtRect); + } + } + + // ===================================================== TOUCH + using stmGesture::CTouchGestureRecogniser; + + if (conf.Enabled(CTouchGestureRecogniser::KUid)) + { + CTouchGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + // define empty area so that touch is reported only inside + // our window (touch recogniser handles either an area or the target window) + gesture->setArea(TRect()); + } + } + + + // ===================================================== PAN + using stmGesture::CPanGestureRecogniser; + + if (conf.Enabled(CPanGestureRecogniser::KUid)) + { + CPanGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setPanningSpeedLow ( conf.Param(stmGesture::EPanSpeedLow) / 1000.f ); + gesture->setPanningSpeedHigh( conf.Param(stmGesture::EPanSpeedHigh) / 1000.f ); + } + } + + // ===================================================== TAP / DOUBLE TAP + /// Add recognizer before any existing Flick, Release, Unknown + // Add the gesture to the gesture engine + // TODO: Tap recognizer is special - it can combine multiple listeners, + // so no need to create new one if it already exists, just add new listeners to it + + using stmGesture::CTapGestureRecogniser; + + if (conf.Enabled(CTapGestureRecogniser::KUid)) + { + CTapGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setDoubleTapTimeout(conf.Param(stmGesture::EDoubleTapTimeout) * 1000); + gesture->setDoubleTapRange( touchAreaSizeInMm ); + gesture->ignoreFirstTap(EFalse); + + aContext.iLogging |= 1<setFlickingSpeed(flickSpeed); + } + } + + // ===================================================== RELEASE + using stmGesture::CReleaseGestureRecogniser; + + if (conf.Enabled(CReleaseGestureRecogniser::KUid)) + { + CReleaseGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setArea(TRect()); + } + } + +#if 0 // use in future depending upon browser requirement + // ===================================================== CORNER ZOOM + using stmGesture::CZoomGestureRecogniser; + + if (conf.Enabled(CZoomGestureRecogniser::KUid)) + { + CZoomGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setArea(ctxtRect); + gesture->setRange(conf.Param(stmGesture::EZoomCornerSize)); + } + } + + // ===================================================== EDGE SCROLL + using stmGesture::CEdgeScrollGestureRecogniser; + + if (conf.Enabled(CEdgeScrollGestureRecogniser::KUid)) + { + CEdgeScrollGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + + if(gesture) + { + gesture->setArea(ctxtRect); + gesture->setScrollRange(conf.Param(stmGesture::EEdgeScrollRange)); // range is 20 pixels from the edge TODO: add this to settings... + } + } + + // ===================================================== LEFT-RIGHT + using stmGesture::CLeftrightGestureRecogniser; + + if (conf.Enabled(CLeftrightGestureRecogniser::KUid)) + { + CLeftrightGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + } + + // ===================================================== UP-DOWN + using stmGesture::CUpdownGestureRecogniser; + + if (conf.Enabled(CUpdownGestureRecogniser::KUid)) + { + CUpdownGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + } + + // ===================================================== HOVER + using stmGesture::CHoveringGestureRecogniser; + + if (conf.Enabled(CHoveringGestureRecogniser::KUid)) + { + CHoveringGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + if(gesture) + { + gesture->setHoveringSpeed(conf.Param(stmGesture::EHoverSpeed) / 1000.f); + } + } + + // ===================================================== UNKNOWN + using stmGesture::CUnknownGestureRecogniser; + + if (conf.Enabled(CUnknownGestureRecogniser::KUid)) + { + CUnknownGestureRecogniser* gesture = NULL; + InitRecognizerL(gesture, aContext, aNewContext); + } +#endif + + // =========================================================== + if(aNewContext) + { + for(TInt i = 0; i < stmGesture::EStmGestureUid_Count; ++i) + { + MStmGestureRecogniser* rec = aContext.iRecognizers[i]; + if(rec) + { + rec->enableLogging(aContext.iLogging & (1<setHoldAreaShape ( stmUiEventEngine::TAreaShape(holdArea.iShape) ); + stateMachine->setHoldArea ( !filter ? 0 : holdAreaSizeInMm ); + stateMachine->setHoldTimeout ( !filter ? 0 : holdArea.iTimeout * 1000); + + // TOUCH-TIME AREA + TStmGestureArea& tTimeArea = *conf.Area(stmGesture::ETouchTimeArea); + TInt tTimeAreaSizeInMm = tTimeArea.iSize.iWidth; + // NB: shape <-- TouchAreaShape + stateMachine->setTouchTimeArea ( !filter ? 0 : tTimeAreaSizeInMm ); + + // Timeouts, Adjustments, etc. + stateMachine->setTouchSuppressTimeout(!filter ? 0 : + conf.Param(stmGesture::ESuppressTimeout)*1000) ; + stateMachine->setMoveSuppressTimeout(!filter ? 0 : + conf.Param(stmGesture::EMoveSuppressTimeout)*1000) ; + stateMachine->enableCapacitiveUp (!filter ? 0 : + conf.Param(stmGesture::ECapacitiveUpUsed)); + stateMachine->enableYadjustment (!filter ? 0 : conf.Param(stmGesture::EAdjustYPos)); + stateMachine->enableLogging(false); + + stateMachine->EnableWsEventMonitoring(false); + LOG("Setup recognizers -- DONE"); + } + +EXPORT_C void CStmGestureEngine::HandlePointerEventL( + const TPointerEvent& aPointerEvent, + void* target) + { + iGf->getUiStateMachine()->HandlePointerEventL(aPointerEvent,target); + } + +// ============================================================= + +CStmGestureContext::CStmGestureContext( + CStmGestureEngine& aEngine ) : + iEngine(aEngine), + iEventSender(NULL) + { + + } + +void CStmGestureContext::ConstructL() + { + iEngine.iContexts.AppendL(this); + iConfig = new(ELeave) CStmGestureParameters(); + } + +CStmGestureContext::~CStmGestureContext() + { + // Remove all gesture listeners + for(TInt i = iListeners.Count() - 1; i >= 0; --i) + { + MStmGestureListener* listener = iListeners[i]; + iListeners.Remove(i); + } + + iListeners.Reset(); + + // Remove all context's recognizers from the Gesture Engine + Deactivate(); + + if (iEventSender) + delete iEventSender; + + // Destroy all recognizers + for(TInt r = 0; r < stmGesture::EStmGestureUid_Count; ++r) + { + MStmGestureRecogniser*& rec = iRecognizers[r]; + if(rec) + { + delete rec; + rec = NULL; + } + } + + // Remove context from the Gesture Engine + TInt idx = iEngine.iContexts.Find(this); + if(idx != -1) + { + iEngine.iContexts.Remove(idx); + } + delete iConfig; + } + +EXPORT_C void CStmGestureContext::AddListenerL( + MStmGestureListener* aListener, + TInt aPos ) + { + iEventSender = CGestureEventSender::NewL(*aListener); + iListeners.InsertL(aListener, aPos); + } + +EXPORT_C TInt CStmGestureContext::RemoveListener( + MStmGestureListener* aListener ) + { + TInt ind = iListeners.Find(aListener); + if(ind >= 0) + { + iListeners.Remove(ind); + } + return ind; + } + +EXPORT_C void CStmGestureContext::SetContext( + CCoeControl* aControl ) + { + iOwnerControl = aControl; + + for(TInt i = 0; i < stmGesture::EStmGestureUid_Count; ++i) + { + MStmGestureRecogniser* rec = iRecognizers[i]; + if(rec) + { + rec->setOwner(aControl); + } + } + } + +EXPORT_C void CStmGestureContext::ActivateL() + { + if(IsActive()) + { + // re-enable all recognizers + EnableRecognizersL(); + return; + } + /// 1. Tell Engine to deactivate active context + + /// 2. Setup all gesture recognizers + iEngine.EnableContextL(*this); + + /// 3. Notify listeners + + // + EnableRecognizersL(); + + /// + iActivated = ETrue; + } + +EXPORT_C void CStmGestureContext::Deactivate() + { + // NB: reactivation of previous context may leave + TRAP_IGNORE(iEngine.DisableContextL(*this)); + iActivated = EFalse; + } + +void CStmGestureContext::gestureEnter( + MStmGesture& aGesture ) + { + TRAP_IGNORE(DispatchGestureEventL(aGesture.gestureUid(), &aGesture)); + } + +void CStmGestureContext::gestureExit( + TStmGestureUid aGestureUid ) + { + TRAP_IGNORE(DispatchGestureEventL(aGestureUid, NULL)); + } + +CCoeControl* CStmGestureContext::getOwner() + { + return iOwnerControl; + } + +void CStmGestureContext::DispatchGestureEventL( + TStmGestureUid aUid, + MStmGesture* aGesture ) + { + iEventSender->AddEvent(aUid, aGesture); + } + +void CStmGestureContext::SuspendRecognizer( + TStmGestureUid aUid ) + { + MStmGestureRecogniser* rec = iRecognizers[aUid]; + if(rec && !rec->isEnabled()) + { + rec->enable(EFalse); + // TODO: Notify listener + } + } + +void CStmGestureContext::EnableRecognizersL() + { + for(TInt i = 0; i < stmGesture::EStmGestureUid_Count; ++i) + { + EnableRecognizerL(TStmGestureUid(i)); + } + } + +void CStmGestureContext::EnableRecognizerL( + TStmGestureUid aUid ) + { + MStmGestureRecogniser* rec = iRecognizers[aUid]; + if(rec && !rec->isEnabled()) + { + rec->enable(ETrue); + // TODO: Notify listener + } + } +