diff -r 4526337fb576 -r 3eca7e70b1b8 mulwidgets/gesturehelper/src/gesturehelperimpl.cpp --- a/mulwidgets/gesturehelper/src/gesturehelperimpl.cpp Tue Feb 02 00:28:09 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,912 +0,0 @@ -/* -* 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 "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 -* -*/ - -#include "gesturehelperimpl.h" - -#include -#include -#include - -#include "gesture.h" -#include "gesturedefs.h" - -#include "pointercapturer.h" - -using namespace GestureHelper; - -namespace GestureHelper -{ - -/// type of function in gesture helper to be called by the timer -/// when timer triggers -typedef void (CGestureHelperImpl::*CallbackFunctionL)(); - -NONSHARABLE_CLASS( CCallbackTimer ) : public CTimer - { -public: - /** Two-phase constructor */ - static CCallbackTimer* NewL( CGestureHelperImpl& aHelper, - CallbackFunctionL aCallbackFunctionL, TInt aDelay, TBool aIsEnabled ) - { - CCallbackTimer* self = new ( ELeave ) CCallbackTimer( aHelper, - aCallbackFunctionL, aDelay, aIsEnabled ); - CleanupStack::PushL( self ); - self->ConstructL(); // construct base class - CActiveScheduler::Add( self ); - CleanupStack::Pop( self ); - return self; - } - - /** Destructor */ - ~CCallbackTimer() - { - Cancel(); - } - - /** Set whether sending holding events is currently enabled */ - void SetEnabled( TBool aEnabled ) - { - iIsEnabled = aEnabled; - // cancel in case hold timer is already running - Cancel(); - } - - /** @return whether sending holding events is currently enabled */ - TBool IsEnabled() const - { - return iIsEnabled; - } - - /** Start the timer. Calls CGestureHelperImpl::StartHoldingL upon completion */ - void Start() - { - // if sending hold events is disabled, do not ever start the hold timer, and - // hence hold events will never be triggered - if ( iIsEnabled ) - { - Cancel(); - After( iDelay ); - } - } - -private: - /** Constructor */ - CCallbackTimer( CGestureHelperImpl& aHelper, - CallbackFunctionL aCallbackFunctionL, TInt aDelay, TBool aIsEnabled ) - : CTimer( EPriorityUserInput - 1 ), // give higher priority to new pointer events with - 1 - iHelper( aHelper ), iCallbackFunctionL( aCallbackFunctionL ), - iDelay( aDelay ), iIsEnabled( aIsEnabled ) - { - } - - void RunL() // From CActive - { - (iHelper.*iCallbackFunctionL)(); - } - -private: - /// helper object that will be called back when timer is triggered - CGestureHelperImpl& iHelper; - /// Function in the iHelper object call - CallbackFunctionL iCallbackFunctionL; - /// How long a time to wait befor calling back after Start() - TInt iDelay; - /// whether sending holding events is currently enabled - TBool iIsEnabled; - }; - -} // namespace GestureHelper - -/** - * @return position from event. Use this instead of using aEvent direction to - * avoid accidentally using TPointerEvent::iPosition - */ -inline TPoint Position( const TPointerEvent& aEvent ) - { - // use parent position, since the capturer is using full screen area, - // and because the (Alfred) drag events are not local to visual even when - // coming from the client - return aEvent.iParentPosition; - } - -// ---------------------------------------------------------------------------- -// Two-phase constructor -// ---------------------------------------------------------------------------- -// -CGestureHelperImpl* CGestureHelperImpl::NewL( MGestureObserver& aObserver ) - { - CGestureHelperImpl* self = new ( ELeave ) CGestureHelperImpl( ); - CleanupStack::PushL( self ); - self->iDoubleTapTimer = CCallbackTimer::NewL( *self, EmitFirstTapEventL, - KMaxDoubleTapDuration, EFalse ); // double tap is disabled by default - self->iHoldingTimer = CCallbackTimer::NewL( *self, StartHoldingL, - KHoldDuration, ETrue ); // holding is enabled by default - self->iGesture = new ( ELeave ) CGesture(); - self->iUnusedGesture = new ( ELeave ) CGesture(); - self->iPointerCapturer = CPointerCapturer::NewL(); - self->iPointerCount = 0; - self->iObserver = &aObserver; - CleanupStack::Pop( self ); - return self; - } - -// ---------------------------------------------------------------------------- -// Destructor -// ---------------------------------------------------------------------------- -// -CGestureHelperImpl::~CGestureHelperImpl() - { - delete iDoubleTapTimer; - delete iHoldingTimer; - delete iGesture; - delete iPreviousTapGesture; - delete iUnusedGesture; - delete iPointerCapturer; - } - -// ---------------------------------------------------------------------------- -// SetHoldingEnabled -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::SetHoldingEnabled( TBool aEnabled ) - { - iHoldingTimer->SetEnabled( aEnabled ); - } - -// ---------------------------------------------------------------------------- -// IsHoldingEnabled -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::IsHoldingEnabled() const - { - return iHoldingTimer->IsEnabled(); - } - -// ---------------------------------------------------------------------------- -// SetHoldingEnabled -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::SetDoubleTapEnabled( TBool aEnabled ) - { - iDoubleTapTimer->SetEnabled( aEnabled ); - } - -// ---------------------------------------------------------------------------- -// IsHoldingEnabled -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::IsDoubleTapEnabled() const - { - return iDoubleTapTimer->IsEnabled(); - } - -// ---------------------------------------------------------------------------- -// InitAlfredPointerEventCaptureL -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::InitAlfredPointerCaptureL( CAlfEnv& aEnv, - CAlfDisplay& aDisplay, TInt aFreeControlGroupId ) - { - iPointerCapturer->InitForAlfredL(*this, aEnv, aDisplay, aFreeControlGroupId ); - } - -// ---------------------------------------------------------------------------- -// Reset state -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::Reset() - { - iHoldingTimer->Cancel(); - iGesture->Reset(); - iPointerCapturer->Stop(); - iPointerCount=0; - iCurrentPointer = -1; - } - -/** - * Helper function that calls Reset on the pointer to CGestureHelperImpl - */ -static void ResetHelper( TAny* aHelper ) - { - static_cast< CGestureHelperImpl* >( aHelper )->Reset(); - } - -// ---------------------------------------------------------------------------- -// Handle a pointer event -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::HandlePointerEventL( const TPointerEvent& aEvent ) - { - return HandlePointerEventL( aEvent, NULL ); - } - -// ---------------------------------------------------------------------------- -// OfferEventL -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::OfferEventL( const TAlfEvent& aEvent ) - { - if ( aEvent.IsPointerEvent() ) - { - return HandlePointerEventL( aEvent.PointerEvent(), aEvent.Visual() ); - } - return EFalse; - } - -// ---------------------------------------------------------------------------- -// Handle a pointer event -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::HandlePointerEventL( const TPointerEvent& aEvent, - CAlfVisual* aVisual ) - { - TInt pointerNumber = GestureHelper::TGestureRecogniser().PointerNumber( aEvent ); - - if( !ValidatePointer( aEvent, pointerNumber ) ) - { - return EFalse; // don't consume - } - - switch ( aEvent.iType ) - { - case TPointerEvent::EButton1Down: - // Error handling for recieveing a button down on the pointer which - // is already touched down - // Here the pointer number shouldnot be considered for validtaing. - // We should consider which pointer is currently touched down - // It can so happen that user has touched was doing pinch and then released his - // 1st finger. and starts to do panning with the second finger still touched down. - // Then again when he touches the first finger, in that case you should be validating these pointers w.r.t - // the pointer numbers of the last touched finger - - // we shouldnot consider pointer number here. If pointer 1 is - // already touched and dragging and we recieve a down of pointer 0 - - if( iPointerCount == 1 ) - { - if(iCurrentPointer == pointerNumber ) - { - TRAP_IGNORE( EmitCancelEventL() ); - Reset(); - } - } - else if( iPointerCount == 2 ) - { - // This case is similar to reciving a pointer up on the pointer - // on which the second down is recieved. We reset all the earlier points - // recieved on this pointer because we assume that some pointer up got - // missed in between. - - // if pointer count is already 2, then reset the array of pointer for - // which a down event is recieved, and continue handling in normal way - // Fix for error crash in photos fullscreen - // Like above if you reset the pointer array for which the down event - // is recieved the second time then in thecase of, 0 down, 1 down, 0 down - // iPoints will be null. - // Here whenever reseting it to single pointer havndling, always iPoints should have - // the data. Hence the first parameter should always be true. - // Fix is iGesture->ResetToLastPoint(pointerNumber != 0,pointerNumber != 0); - // is changed to iGesture->ResetToLastPoint( ETrue,pointerNumber != 0); - iPointerCount = 1; - iCurrentPointer = pointerNumber == 0 ? 1 : 0; - iGesture->ResetToLastPoint( ETrue,pointerNumber != 0); - iGesture->SetSingleTouchActive(); - } - - if(iPointerCount == 0) - { - iPointerCount = 1; - iCurrentPointer = pointerNumber; - // single touch gesture start - iGesture->SetSingleTouchActive(); - HandleSinglePointerEventL( aEvent, aVisual ); - } - else if(iPointerCount == 1) - { - iPointerCount = 2; - iCurrentPointer = -1; - // add the last point of the single touch event - // to first array of gesture - iGesture->ResetToLastPoint(pointerNumber != 0,ETrue); - iGesture->SetMultiTouchActive(); - // multi touch gesture start - HandleMultiplePointerEventL( aEvent, pointerNumber ); - } - else - { - - } - break; - - case TPointerEvent::EDrag: - if(iPointerCount == 1) - { - HandleSinglePointerEventL( aEvent, aVisual ); - } - else if(iPointerCount == 2) - { - HandleMultiplePointerEventL( aEvent, pointerNumber ); - } - else - { - // nothing to be done - } - break; - - case TPointerEvent::EButton1Up: - if(iPointerCount == 2) - { - // multi touch gesture complete - HandleMultiplePointerEventL( aEvent, pointerNumber ); - // should the pointer count decrese first n then - // handling of event or otherwise - iPointerCount = 1; - iCurrentPointer = pointerNumber == 0 ? 1 : 0; - iGesture->ResetToLastPoint(ETrue,pointerNumber != 0); - iGesture->SetSingleTouchActive(); - } - else if( iPointerCount == 1 ) - { - iPointerCount = 0; - iCurrentPointer = -1; - // single touch gesture complete - HandleSinglePointerEventL( aEvent, aVisual ); - } - else - { - // nothing to be done - } - break; - - default: - break; - } - return ETrue; // consume - } -// ---------------------------------------------------------------------------- -// Handle a pointer event -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::HandleSinglePointerEventL( const TPointerEvent& aEvent, - CAlfVisual* aVisual ) - { - switch ( aEvent.iType ) - { - case TPointerEvent::EButton1Down: - // If no up event was received during previous gesture, cancel - // previous event and reset state - if ( !IsIdle() ) - { - // ambiguous what is the right thing when "cancel" event leaves - // and "start" does not. Leaving for cancel *after* "start" could - // be unexpected to client, as client would have handled start - // event successfully. Assume that leaving upon cancellation - // can be ignored. - TRAP_IGNORE( EmitCancelEventL() ); - Reset(); - } - // as long as down event of a double tap comes within the double - // tap timeout, it does not matter how long the user keeps the finger - // pressed for the gesture to be a double tap. Therefore, cancel - // the timeout, as it is no longer relevant. (Of course, this call - // will only do something if the timer is actually running, which - // is only if received a tap event very recently.) - iDoubleTapTimer->Cancel(); - // adding the first point implicitly makes the state "not idle" - AddPointL( aEvent ); - iGesture->SetVisual( aVisual ); - // if pointer capturer leaves, the remaining pointer events will - // not be captured if stylus is dragged outside the capturing visual - // an error note will be shown, so the potential problem is irrelevant, - // assuming client does not (incorrectly) block the leave from reaching - // the framework - iPointerCapturer->StartL(); - // Delay emitting a down event _until_ it is known that this beginning - // gesture is _not_ the second tap of a double tap event. - // iPreviousTapGesture is only non-null if very recently received - // a tap event and double tap is enabled. - if ( !iPreviousTapGesture ) - { - EmitEventL( *iGesture ); - } - // else delay emitting an event, as it might be a double tap - // (allow the second tap of a double tap to be anywhere, so don't check - // for start pos here) - break; - - case TPointerEvent::EDrag: - // While stylus down, the same event is received repeatedly - // even if stylus does not move. Filter out by checking if point - // is the same as the latest point - if ( !iGesture->IsLatestPoint( Position( aEvent ) ) ) - { - AddPointL( aEvent ); - - // as long as the starting gesture is seen as a tap, do not emit any - // drag events - if ( !iGesture->IsTap() ) - { - // if there is a previous tap gesture, getting drag events means that - // the previous gesture is not a double tap. So emit the previous gesture. - if ( iPreviousTapGesture ) - { - // this is a second gesture after a tap (double tap is enabled) - EmitFirstTapEventL(); - // emit down event for the current gesture (since its down was delayed, until - // it was to be known if the event is a tap. That is known now.) - EmitStartEventL( *iGesture ); - } - // restart holding timer every time the current stylus pos changes - StartHoldingTimer( aEvent ); - // emit the drag event to client - EmitEventL( *iGesture ); - } - // else: do not emit drag events until it is known that the gesture is not a tap - // (or the second tap of double tap) - } - break; - - case TPointerEvent::EButton1Up: - // reset in case the down event for next gesture is not received for a reason - // in client, and instead drag or up events are received. - // reset via cleanup stack to ensure Reset is run even if - // observer leaves - CleanupStack::PushL( TCleanupItem( &ResetHelper, this ) ); - // if adding of the point fails, notify client with a - // cancelled event. It would be wrong to send another - // gesture code when the up point is not known - if ( KErrNone == AddPoint( aEvent ) ) - { - // if the gesture is a tap, the gesture is either the first tap of a _potential_ - // double tap, or the second tap of a double tap - if ( iDoubleTapTimer->IsEnabled() && iGesture->IsTap() ) - { - __ASSERT_DEBUG( !iGesture->IsHolding(), Panic( EGesturePanicIllegalLogic ) ); - if ( !iPreviousTapGesture ) - { - // First tap. Delay emitting its code evemt and released events until it is known - // whether the tap is a double tap - iPreviousTapGesture = iGesture; - iGesture = NewGesture(); - iDoubleTapTimer->Start(); - } - else - { - // This is a second tap of a double tap. Do not emit anything for the second - // tap. Only down event has been emitted for the first tap. Emit the code - // event (double tap) and released for the first tap. - iPreviousTapGesture->SetDoubleTap(); - EmitFirstTapEventL(); - } - } - else - { - // modified iGesture to be "released" - CompleteAndEmitSingleTouchL( *iGesture ); - } - } - else - { // adding a point failed - EmitCancelEventL(); - } - // reset state - CleanupStack::PopAndDestroy( this ); - break; - - default: - break; - } - return ETrue; // consume - } - -// ---------------------------------------------------------------------------- -// Handle multiple pointer events -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::HandleMultiplePointerEventL( const TPointerEvent& aEvent, - const TInt aPointerNumber ) - { - switch ( aEvent.iType ) - { - case TPointerEvent::EButton1Down: - // adding the first point implicitly makes the state "not idle" - AddMultiTouchPointsL( aEvent, aPointerNumber); - EmitEventL( *iGesture ); - break; - - case TPointerEvent::EDrag: - // While stylus down, the same event is received repeatedly - // even if stylus does not move. Filter out by checking if point - // is the same as the latest point - if( AddMultiTouchPointsL(aEvent, aPointerNumber )) - { - // as long as the starting gesture is seen as a tap, do not emit any - // drag events - if ( iGesture->IsPinch() ) - { - // emit the pinch event to client - EmitEventL( *iGesture ); - } - // else: do not emit any events to the client - } - - - break; - - case TPointerEvent::EButton1Up: - - // if adding of the point fails, notify client with a - // cancelled event. It would be wrong to send another - // gesture code when the up point is not known - AddMultiTouchPointsL(aEvent, aPointerNumber ); - CompleteAndEmitDoubleTouchL( *iGesture ); - - break; - - default: - break; - } - return ETrue; // consume - } - -// ---------------------------------------------------------------------------- -// Validate AddMultiTouchPointsL events -// Check if the point recieved is the repeavt event of previous point or a new point -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline TBool CGestureHelperImpl::AddMultiTouchPointsL( const TPointerEvent& aEvent, const TInt aPointerNumber) - { - TBool pointAdded = EFalse; - if ( aPointerNumber > 0 ) - { - if ( !iGesture->IsLatestSecondaryPoint( Position( aEvent ) ) ) - { - AddSecondaryPointL( aEvent ); - pointAdded = ETrue; - } - } - else - { - if ( !iGesture->IsLatestPoint( Position( aEvent ) ) ) - { - AddPointL( aEvent ); - pointAdded = ETrue; - } - } - return pointAdded; - } - -// ---------------------------------------------------------------------------- -// Check for Stray evnet -// ---------------------------------------------------------------------------- -// -TBool CGestureHelperImpl::StrayEvent( const TPointerEvent& aEvent ) const - { - //If we are recieving a button down on pointer 0 in pointer capturer then its a stray event - // Dont consume it - if ( aEvent.iType == TPointerEvent::EButton1Down && IsIdle( 0) ) - { - return ETrue; // don't consume - } - return EFalse; - } -// ---------------------------------------------------------------------------- -// Validate the events -// is it a valid event or a stray pointer form some other visuals -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline TBool CGestureHelperImpl::ValidatePointer( const TPointerEvent& aEvent, const TInt aPointerNumber) const - { - // Check if received event is valid or not. - // In practice, event is NOT valid in the following situations: - // - // 1. Pointer down event is received for pointer which is already down. - // 2. Pointer up event is received for pointer which is already up. - // 3. Pointer drag event is received for pointer which is not down. - // 4. Pointer numbers other than 0 and 1. We are handling only 2 pointers. - // - // In these situations this function returns EFalse, - // corresponding event is ignored and recognition continues as earlier. - // - - // filter all the events for which the pointer number is less than 0 - // or greater than 1. we will handle only 2 pointer events. - if( aPointerNumber >= 2 || aPointerNumber < 0 ) - { - return EFalse; - } - - // filter out events that do not start with button down. It is a stray - // event from another visual - TInt pointerTovalidate = aPointerNumber ; - if( iPointerCount == 1 && aPointerNumber == 1) - { - pointerTovalidate = 0; - } - if ( aEvent.iType != TPointerEvent::EButton1Down && IsIdle( pointerTovalidate ) ) - { - return EFalse; // don't consume - } - - - return ETrue; - } - -// ---------------------------------------------------------------------------- -// Is the helper idle? -// Checks whether any points are already added in the array corresponding -// to the pointer number -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline TBool CGestureHelperImpl::IsIdle( TBool aPointerNumber ) const - { - if( aPointerNumber == 0 ) - { - return iGesture->IsEmpty(); - } - else if( aPointerNumber == 1 ) - { - return iGesture->IsMultiTouch(); - } - return ETrue; - } - -// ---------------------------------------------------------------------------- -// Add a point to the sequence of points that together make up the gesture -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline void CGestureHelperImpl::AddPointL( const TPointerEvent& aEvent ) - { - User::LeaveIfError( AddPoint( aEvent ) ); - } - -// ---------------------------------------------------------------------------- -// Add a point to the sequence of points that together make up the gesture -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline TInt CGestureHelperImpl::AddPoint( const TPointerEvent& aEvent ) - { - return iGesture->AddPoint( Position ( aEvent ) ); - } - -// ---------------------------------------------------------------------------- -// Add a point to the sequence of points that together make up the gesture -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline void CGestureHelperImpl::AddSecondaryPointL( const TPointerEvent& aEvent ) - { - User::LeaveIfError( AddSecondaryPoint( aEvent ) ); - } - -// ---------------------------------------------------------------------------- -// Add a point to the sequence of points that together make up the gesture -// inline ok in cpp file for a private member function -// ---------------------------------------------------------------------------- -// -inline TInt CGestureHelperImpl::AddSecondaryPoint( const TPointerEvent& aEvent ) - { - return iGesture->AddSecondaryPoint( Position ( aEvent ) ); - } - -// ---------------------------------------------------------------------------- -// StartHoldingTimer -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::StartHoldingTimer( const TPointerEvent& aNewEvent ) - { - if ( !( iGesture->IsHolding() || - iGesture->IsNearHoldingPoint( Position( aNewEvent ) ) ) ) - { - // restart hold timer, since pointer has moved - iHoldingTimer->Start(); - // Remember the point in which holding was started - iGesture->SetHoldingPoint(); - } - } - -/** - * Helper function that calls ContinueHolding on the pointer to TGesture - */ -static void ContinueHolding( TAny* aGesture ) - { - static_cast< CGesture* >( aGesture )->ContinueHolding(); - } - -// ---------------------------------------------------------------------------- -// Add a point to the sequence of points that together make up the gesture -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::StartHoldingL() - { - // hold & tap event is specifically filtered out. Use case: in list fast - // scrolling activation (e.g. enhanced coverflow), tap & hold should not - // start fast scroll. In addition, after long tap on start position, - // drag and drag & hold swiping should emit normal swipe and swipe&hold - // events. Therefore, tap & hold is not supported. - __ASSERT_DEBUG( !iGesture->IsTap() && !iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) ); - - // holding has just started, and gesture code should be provided to client. - // set gesture state so that it produces a gesture code (other than drag) - iGesture->StartHolding(); - - // create an item in the cleanup stack that will set the gesture state - // to holding-was-started-earlier state. NotifyL may leave, but the - // holding-was-started-earlier state must still be successfully set, - // otherwise, the holding gesture code will be sent twice - CleanupStack::PushL( TCleanupItem( &ContinueHolding, iGesture ) ); - - EmitEventL( *iGesture ); - - // set holding state to "post holding" - CleanupStack::PopAndDestroy( iGesture ); - } - -// ---------------------------------------------------------------------------- -// RecyclePreviousTapGesture -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::RecyclePreviousTapGesture( TAny* aSelf ) - { - CGestureHelperImpl& self = *reinterpret_cast( aSelf ); - self.RecycleGesture( self.iPreviousTapGesture ); - } - -// ---------------------------------------------------------------------------- -// Emit the remainder of the previous tap event (tap + released) -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::EmitFirstTapEventL() - { - // when this function is called, a tap has turned out to _not_ be a double tap - __ASSERT_DEBUG( IsDoubleTapEnabled(), Panic( EGesturePanicIllegalLogic ) ); - __ASSERT_DEBUG( iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) ); - - iDoubleTapTimer->Cancel(); - - // ensure previous tap gesture is reset even if client leaves - CleanupStack::PushL( TCleanupItem( &RecyclePreviousTapGesture, this ) ); - - CompleteAndEmitSingleTouchL( *iPreviousTapGesture ); - - // recycle the emitted gesture - CleanupStack::PopAndDestroy( this ); - } - -// ---------------------------------------------------------------------------- -// EmitStartEventL -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::EmitStartEventL( const CGesture& aGesture ) - { - CGesture* startGesture = aGesture.AsStartEventLC(); - EmitEventL( *startGesture ); - CleanupStack::PopAndDestroy( startGesture ); - } - -// ---------------------------------------------------------------------------- -// EmitCompletionEvents for single touch -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::CompleteAndEmitSingleTouchL( CGesture& aGesture ) - { - aGesture.SetSingleTouchComplete(); - // send gesture code if holding has not been started. If holding has - // been started, client has already received a "hold swipe left" e.g. event, in which - // case don't another "swipe left" event - if ( !aGesture.IsHolding() ) - { - // if client leaves, the state is automatically reset. - // In this case the client will not get the released event - EmitEventL( aGesture ); - } - // send an event that stylus was lifted - aGesture.SetSingleTouchReleased(); - EmitEventL( aGesture ); - } - -// ---------------------------------------------------------------------------- -// EmitCompletionEvents for double touch -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::CompleteAndEmitDoubleTouchL( CGesture& aGesture ) - { - aGesture.SetMultiTouchComplete(); - if ( aGesture.IsPinch() ) - { - // emit the pinch event to client - EmitEventL( aGesture ); - } - // send an event that stylus was lifted - aGesture.SetMultiTouchReleased(); - EmitEventL( aGesture ); - } - -// ---------------------------------------------------------------------------- -// EmitCancelEventL -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::EmitCancelEventL() - { - iDoubleTapTimer->Cancel(); - - // ensure previous tap gesture is reset even if client leaves - CleanupStack::PushL( TCleanupItem( &RecyclePreviousTapGesture, this ) ); - - CGesture& gestureToCancel = iPreviousTapGesture ? *iPreviousTapGesture : *iGesture; - gestureToCancel.SetCancelled(); - EmitEventL( gestureToCancel ); - - // recycle the emitted gesture - CleanupStack::PopAndDestroy( this ); - } - -// ---------------------------------------------------------------------------- -// Notify observer -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::EmitEventL( const CGesture& aGesture ) - { - // iPoints array must have content when this function is called - iObserver->HandleGestureL( aGesture ); - } - -// ---------------------------------------------------------------------------- -// Return a fresh gesture from the gesture pool (pool of one gesture) -// ---------------------------------------------------------------------------- -// -CGesture* CGestureHelperImpl::NewGesture() - { - __ASSERT_DEBUG( iUnusedGesture, Panic( EGesturePanicIllegalLogic ) ); // pool should no be empty - iUnusedGesture->Reset(); - CGesture* freshGesture = iUnusedGesture; - iUnusedGesture = NULL; - return freshGesture; - } - -// ---------------------------------------------------------------------------- -// Return a fresh gesture from the gesture pool (pool of one gesture) -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::RecycleGesture( CGesture*& aGesturePointer ) - { - // only one object fits into the pool, and that should currently be enough - // one pointer must be null, one non-null - __ASSERT_DEBUG( !iUnusedGesture != !aGesturePointer, Panic( EGesturePanicIllegalLogic ) ); - if ( aGesturePointer ) - { - iUnusedGesture = aGesturePointer; - aGesturePointer = NULL; - } - } - -// ---------------------------------------------------------------------------- -// AddObserver -// ---------------------------------------------------------------------------- -// -void CGestureHelperImpl::AddObserver(MGestureObserver* aObserver) - { - iObserver = aObserver; - } - -// end of file -