diff -r 000000000000 -r 2f259fa3e83a akntouchgesturefw/src/akntouchgesturefwtaprecognizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/akntouchgesturefw/src/akntouchgesturefwtaprecognizer.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,432 @@ +/* +* Copyright (c) 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: Tap touch gesture recognizer. +* +*/ + +#include "akntouchgesturefwdefs.h" +#include "akntouchgesturefwevent.h" +#include "akntouchgesturefwsettings.h" +#include "akntouchgesturefwtaprecognizer.h" + +using namespace AknTouchGestureFw; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewL( + CAknTouchGestureFwRecognitionEngine& aEngine ) + { + CAknTouchGestureFwTapRecognizer* self = + CAknTouchGestureFwTapRecognizer::NewLC( aEngine ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewLC( + CAknTouchGestureFwRecognitionEngine& aEngine ) + { + CAknTouchGestureFwTapRecognizer* self + = new ( ELeave ) CAknTouchGestureFwTapRecognizer( aEngine ); + CleanupStack::PushL( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwTapRecognizer::~CAknTouchGestureFwTapRecognizer() + { + if ( iLongTapTimer ) + { + iLongTapTimer->Cancel(); + } + delete iLongTapTimer; + } + + +// --------------------------------------------------------------------------- +// Returns the tap gesture group. +// --------------------------------------------------------------------------- +// +TAknTouchGestureFwGroup CAknTouchGestureFwTapRecognizer::GestureGroup() const + { + return EAknTouchGestureFwGroupTap; + } + + +// --------------------------------------------------------------------------- +// Cancels the tap recognition. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::CancelRecognizing() + { + DoCancelTapRecognition( ETrue ); + } + + +// --------------------------------------------------------------------------- +// Handles single-touch pointer events. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::HandleSinglePointerEventL( + const TPointerEventData& aPointerData ) + { + switch ( aPointerData.iPointerEvent.iType ) + { + case TPointerEvent::EButton1Down: + { + // Start recognition on down event + StartTapRecognition( + aPointerData.iPointerEvent.iPosition, + aPointerData.iTimeStamp ); + break; + } + case TPointerEvent::EDrag: + { + // Continue tap recognizing. + TapRecognize( aPointerData.iPointerEvent.iPosition ); + break; + } + case TPointerEvent::EButton1Up: + { + // Pointer up - complete recognition + CompleteTapRecognitionL( aPointerData.iTimeStamp ); + break; + } + default: + { + break; + } + } + } + + +// --------------------------------------------------------------------------- +// Handles multi-touch pointer events. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::HandleMultiPointerEventL( + const TPointerEventData& aPointerData, + const TPoint& /*aFirstPointerPosition*/, + const TPoint& /*aSecondPointerPosition*/ ) + { + if ( aPointerData.iPointerEvent.iType == TPointerEvent::EButton1Down ) + { + // First pointer is already down, second pointer down cancels tap + // recognizing because taps are allowed only for the first pointer. + CancelRecognizing(); + } + } + + +// --------------------------------------------------------------------------- +// C++ constructor. +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwTapRecognizer::CAknTouchGestureFwTapRecognizer( + CAknTouchGestureFwRecognitionEngine& aEngine ) + : CAknTouchGestureFwBaseRecognizer( aEngine ), + iThresholdArea(), + iLongTapTimer( NULL ), + iFirstTapDetected( EFalse ), + iFirstTapTime(), + iFirstTapPos(), + iLongTapIntensity( 0 ), + iFeedBackStarted( EFalse ) + { + } + + +// --------------------------------------------------------------------------- +// Starts the tap gesture recognition. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::StartTapRecognition( + const TPoint& aStartPoint, + const TTime& aTimeStamp ) + { + iThresholdArea.Start( aStartPoint ); + + // Start timer to recognize long tap + if ( !iLongTapTimer ) + { + iLongTapTimer = CPeriodic::New( CActive::EPriorityStandard ); + } + + if ( iLongTapTimer ) + { + iLongTapTimer->Cancel(); + // Set timer for initial long tap delay. + iLongTapTimer->Start( KDefaultLongTapInitialDelay, + KDefaultLongTapInitialDelay, + TCallBack( LongTapCallback, this ) ); + } + + if ( iFirstTapDetected ) + { + // First tap already detected, check if this tap is double tap + + // Check if position of this tap is too far from + // position of first tap. + TInt xDistance = Abs( aStartPoint.iX - iFirstTapPos.iX ); + TInt yDistance = Abs( aStartPoint.iY - iFirstTapPos.iY ); + + if ( xDistance > DragThreshold() || yDistance > DragThreshold() ) + { + // Too far, this tap can't be double tap. + iFirstTapDetected = EFalse; + return; + } + + // Check if delay between already detected tap and this tap is too long. + TInt delay( aTimeStamp.MicroSecondsFrom( iFirstTapTime ).Int64() ); + + if ( delay > DoubleTapMaximumDuration() ) + { + // Delay is too long, this tap can't be double tap. + iFirstTapDetected = EFalse; + } + } + } + + +// --------------------------------------------------------------------------- +// Continues the tap gesture recognition, called on drag pointer events. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::TapRecognize( const TPoint& aPoint ) + { + if ( iThresholdArea.Check( aPoint, TapThreshold() ) ) + { + CancelRecognizing(); + } + } + + +// --------------------------------------------------------------------------- +// Ends the tap gesture recognition. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::CompleteTapRecognitionL( + const TTime& aTimeStamp ) + { + if ( iThresholdArea.IsActive() ) + { + // Single pointer has been down and goes up now + // and tap recognition hasn't been cancelled + const TPoint startPos( iThresholdArea.InitialPosition() ); + + // Cancel tap recognition of this tap, but don't + // remove the possible info that first tap has already been detected + DoCancelTapRecognition( EFalse ); + + if ( iFirstTapDetected ) + { + iFirstTapDetected = EFalse; + // First tap already detected: Send Double Tap gesture event + SendTapEventL( EAknTouchGestureFwDoubleTap, iFirstTapPos ); + } + else + { + iFirstTapTime = aTimeStamp; + iFirstTapDetected = ETrue; + iFirstTapPos = startPos; + + // First tap not detected: Send normal Tap gesture event + SendTapEventL( EAknTouchGestureFwTap, startPos ); + } + } + } + + +// --------------------------------------------------------------------------- +// Sends a tap gesture event to the observer. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::SendTapEventL( + TAknTouchGestureFwType aGestureType, + const TPoint& aPointerPos ) + { + TTouchFeedbackType feedbackType( FeedbackType( aGestureType ) ); + if ( feedbackType ) + { + switch ( aGestureType ) + { + case EAknTouchGestureFwTap: + { + ImmediateFeedback( ETouchFeedbackSensitive, feedbackType ); + break; + } + case EAknTouchGestureFwDoubleTap: + { + ImmediateFeedback( ETouchFeedbackBasic, feedbackType ); + break; + } + case EAknTouchGestureFwLongTap: + { + ImmediateFeedback( ETouchFeedbackBasic, feedbackType ); + break; + } + default: + { + break; + } + } + } + + TAknTouchGestureFwTapEvent tap; + tap.SetType( aGestureType ); + tap.SetPosition( aPointerPos ); + SendGestureEventL( tap ); + } + + +// --------------------------------------------------------------------------- +// Called when long tap has been detected. +// --------------------------------------------------------------------------- +// +TInt CAknTouchGestureFwTapRecognizer::LongTapCallback( TAny* aThis ) + { + CAknTouchGestureFwTapRecognizer* recognizer = + static_cast( aThis ); + if ( recognizer ) + { + TRAP_IGNORE( recognizer->HandleLongTapCallbackL() ); + } + return 0; + } + + +// --------------------------------------------------------------------------- +// Handles long tap callback related actions. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::HandleLongTapCallbackL() + { + if ( iLongTapIntensity == 0 && iLongTapTimer ) + { + iLongTapTimer->Cancel(); + + TInt interval = ( LongTapThreshold() - KDefaultLongTapInitialDelay ) + / KDefaultMaxLongTapIntensitySteps; + + TInt timeOut = + interval * ( KDefaultMaxLongTapIntensitySteps + 1 ); + + // Start timer again to increase long tap intensity on + // regular interval until max intensity is reached. + iLongTapTimer->Start( 0, interval, + TCallBack( LongTapCallback, this ) ); + + TTouchFeedbackType feedbackType( + FeedbackType( EAknTouchGestureFwTap ) ); + + if ( feedbackType & ETouchFeedbackVibra ) + { + // Start feedback for long tap gesture. + StartContinuousFeedback( ETouchContinuousSmooth, 0, timeOut ); + iFeedBackStarted = ETrue; + } + } + + // Calculate new long tap intensity value. + iLongTapIntensity = iLongTapIntensity + + KDefaultMaxLongTapIntensity / KDefaultMaxLongTapIntensitySteps; + + if ( iFeedBackStarted ) + { + // Modify existing continuous feedback. Intensity will grow + // from 0 to 100 and after that long tap is detected. + ModifyContinuousFeedback( iLongTapIntensity ); + } + + if ( iLongTapIntensity >= KDefaultMaxLongTapIntensity ) + { + const TPoint startPos( iThresholdArea.InitialPosition() ); + CancelRecognizing(); + // Send Long Tap gesture event. + SendTapEventL( EAknTouchGestureFwLongTap, startPos ); + } + } + + +// --------------------------------------------------------------------------- +// Cancels the tap gesture recognition. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwTapRecognizer::DoCancelTapRecognition( + TBool aResetFirstTapDetection ) + { + iThresholdArea.Reset(); + + if ( aResetFirstTapDetection ) + { + iFirstTapDetected = EFalse; + } + + if ( iLongTapTimer ) + { + iLongTapTimer->Cancel(); + + if ( iLongTapIntensity > 0 ) + { + StopContinuousFeedback(); + iFeedBackStarted = EFalse; + iLongTapIntensity = 0; + } + } + } + + +// --------------------------------------------------------------------------- +// Returns the value for the long tap threshold setting. +// --------------------------------------------------------------------------- +// +TInt CAknTouchGestureFwTapRecognizer::LongTapThreshold() const + { + return Settings().LongTapThreshold() * KMicroSecondsInMilliSecond; + } + + +// --------------------------------------------------------------------------- +// Returns the value for the single tap threshold setting. +// --------------------------------------------------------------------------- +// +TInt CAknTouchGestureFwTapRecognizer::TapThreshold() const + { + return Settings().TapThreshold(); + } + + +// --------------------------------------------------------------------------- +// Returns the value for the double tap maximum duration setting. +// --------------------------------------------------------------------------- +// +TInt CAknTouchGestureFwTapRecognizer::DoubleTapMaximumDuration() const + { + return Settings().DoubleTapMaximumDuration() * KMicroSecondsInMilliSecond; + } + +// End of File