webengine/webkitutils/rt_gesturehelper/src/gesturehelperimpl.cpp
branchRCL_3
changeset 93 79859ed3eea9
equal deleted inserted replaced
92:e1bea15f9a39 93:79859ed3eea9
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Gesture helper implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "gesturehelperimpl.h"
       
    20 
       
    21 #include <e32base.h>
       
    22 #include <w32std.h>
       
    23 
       
    24 #include "gesture.h"
       
    25 #include "gesturedefs.h"
       
    26 #include "utils.h"
       
    27 #include "gestureeventfilter.h"
       
    28 #include "gesturehelpereventsender.h"
       
    29 #include "flogger.h"
       
    30 
       
    31 using namespace RT_GestureHelper;
       
    32 
       
    33 namespace RT_GestureHelper
       
    34 {
       
    35 
       
    36 /// type of function in gesture helper to be called by the timer
       
    37 /// when timer triggers
       
    38 typedef void (CGestureHelperImpl::*CallbackFunctionL)();
       
    39 
       
    40 NONSHARABLE_CLASS( CCallbackTimer ) : public CTimer
       
    41     {
       
    42 public:
       
    43     /** Two-phase constructor */
       
    44     static CCallbackTimer* NewL( CGestureHelperImpl& aHelper, 
       
    45             CallbackFunctionL aCallbackFunctionL, TInt aDelay, TBool aIsEnabled )
       
    46         {
       
    47         CCallbackTimer* self = new ( ELeave ) CCallbackTimer( aHelper, 
       
    48             aCallbackFunctionL, aDelay, aIsEnabled );
       
    49         CleanupStack::PushL( self );
       
    50         self->ConstructL(); // construct base class
       
    51         CActiveScheduler::Add( self );
       
    52         CleanupStack::Pop( self );
       
    53         return self;
       
    54         }
       
    55         
       
    56     /** Destructor */
       
    57     ~CCallbackTimer()
       
    58         {
       
    59         Cancel();
       
    60         }
       
    61         
       
    62     /** Set whether sending holding events is currently enabled */
       
    63     void SetEnabled( TBool aEnabled )
       
    64         {
       
    65         iIsEnabled = aEnabled;
       
    66         // cancel in case hold timer is already running
       
    67         Cancel();
       
    68         }
       
    69         
       
    70     /** @return whether sending holding events is currently enabled */
       
    71     TBool IsEnabled() const
       
    72         {
       
    73         return iIsEnabled;
       
    74         }
       
    75         
       
    76     /** Start the timer. Calls CGestureHelperImpl::StartHoldingL upon completion */
       
    77     void Start()
       
    78         {
       
    79         // if sending hold events is disabled, do not ever start the hold timer, and 
       
    80         // hence hold events will never be triggered
       
    81         if ( iIsEnabled ) 
       
    82             {
       
    83             Cancel();
       
    84             After( iDelay );
       
    85             }
       
    86         }    
       
    87     void SetDelay(TInt aDelay) { iDelay = aDelay; }
       
    88     TInt GetDelay() { return iDelay; }
       
    89     
       
    90 private:    
       
    91     /** Constructor */
       
    92     CCallbackTimer( CGestureHelperImpl& aHelper,
       
    93         CallbackFunctionL aCallbackFunctionL, TInt aDelay, TBool aIsEnabled )
       
    94             : CTimer( EPriorityUserInput - 1 ), // give higher priority to new pointer events with - 1
       
    95                 iHelper( aHelper ), iCallbackFunctionL( aCallbackFunctionL ), 
       
    96                     iDelay( aDelay ), iIsEnabled( aIsEnabled ) 
       
    97         {
       
    98         }
       
    99         
       
   100     void RunL() // From CActive
       
   101         {
       
   102         (iHelper.*iCallbackFunctionL)();
       
   103         }
       
   104 
       
   105 private:
       
   106     /// helper object that will be called back when timer is triggered
       
   107     CGestureHelperImpl& iHelper;
       
   108     /// Function in the iHelper object call 
       
   109     CallbackFunctionL iCallbackFunctionL;
       
   110     /// How long a time to wait befor calling back after Start()
       
   111     TInt iDelay;
       
   112     /// whether sending holding events is currently enabled
       
   113     TBool iIsEnabled;
       
   114     };
       
   115 
       
   116 } // namespace GestureHelper
       
   117 
       
   118 /** 
       
   119  * @return position from event. Use this instead of using aEvent direction to
       
   120  *         avoid accidentally using TPointerEvent::iPosition
       
   121  */
       
   122 inline TPoint Position( const TPointerEvent& aEvent )
       
   123     {
       
   124     // use parent position, since the capturer is using full screen area,
       
   125     // and because the (Alfred) drag events are not local to visual even when
       
   126     // coming from the client
       
   127     
       
   128     return aEvent.iPosition;
       
   129     }
       
   130 
       
   131 // ----------------------------------------------------------------------------
       
   132 // Two-phase constructor
       
   133 // ----------------------------------------------------------------------------
       
   134 //
       
   135 CGestureHelperImpl* CGestureHelperImpl::NewL( MGestureObserver& aObserver )
       
   136     {
       
   137     CGestureHelperImpl* self = new ( ELeave ) CGestureHelperImpl( aObserver );
       
   138     CleanupStack::PushL( self );
       
   139     self->iEventSender = CGestureEventSender::NewL( aObserver );
       
   140     self->iDoubleTapTimer = CCallbackTimer::NewL( *self, &CGestureHelperImpl::EmitFirstTapEvent, 
       
   141             KMaxTapDuration, EFalse ); // double tap is disabled by default
       
   142     self->iHoldingTimer = CCallbackTimer::NewL( *self, &CGestureHelperImpl::StartHoldingL, 
       
   143         KHoldDuration, EFalse ); // holding is enabled by default
       
   144     
       
   145     self->iLongTouchTimer = CCallbackTimer::NewL( *self, &CGestureHelperImpl::HandleLongTouch, 
       
   146             KLongTapDuration, ETrue ); // holding is enabled by default
       
   147     
       
   148     self->iGesture = new ( ELeave ) CGesture();
       
   149     self->iUnusedGesture = new ( ELeave ) CGesture();
       
   150     TInt tapLimit = Mm2Pixels(KFingerSize_mm) / 2;
       
   151     self->iEventFilter = new (ELeave) CGestureEventFilter(tapLimit);
       
   152     CleanupStack::Pop( self );
       
   153     return self;
       
   154     }
       
   155 
       
   156 // ----------------------------------------------------------------------------
       
   157 // Constructor
       
   158 // ----------------------------------------------------------------------------
       
   159 //
       
   160 CGestureHelperImpl::CGestureHelperImpl( MGestureObserver& aObserver )
       
   161         : iObserver( aObserver )
       
   162     {
       
   163     }
       
   164 
       
   165 // ----------------------------------------------------------------------------
       
   166 // Destructor
       
   167 // ----------------------------------------------------------------------------
       
   168 //
       
   169 CGestureHelperImpl::~CGestureHelperImpl()
       
   170     {
       
   171     delete iDoubleTapTimer;
       
   172     delete iHoldingTimer;
       
   173     delete iGesture;
       
   174     delete iPreviousTapGesture;
       
   175     delete iUnusedGesture;
       
   176     delete iLongTouchTimer;
       
   177     delete iEventFilter;
       
   178     delete iEventSender;
       
   179     }
       
   180     
       
   181 
       
   182 // ----------------------------------------------------------------------------
       
   183 // SetHoldingEnabled
       
   184 // ----------------------------------------------------------------------------
       
   185 //
       
   186 void CGestureHelperImpl::SetHoldingEnabled( TBool aEnabled )
       
   187     {
       
   188     iHoldingTimer->SetEnabled( aEnabled );
       
   189     }
       
   190 
       
   191 // ----------------------------------------------------------------------------
       
   192 // IsHoldingEnabled
       
   193 // ----------------------------------------------------------------------------
       
   194 //
       
   195 TBool CGestureHelperImpl::IsHoldingEnabled() const
       
   196     {
       
   197     return iHoldingTimer->IsEnabled();
       
   198     }
       
   199 
       
   200 // ----------------------------------------------------------------------------
       
   201 // SetHoldingEnabled
       
   202 // ----------------------------------------------------------------------------
       
   203 //
       
   204 void CGestureHelperImpl::SetDoubleTapEnabled( TBool aEnabled )
       
   205     {
       
   206     iDoubleTapTimer->SetEnabled( aEnabled );
       
   207     }
       
   208 
       
   209 // ----------------------------------------------------------------------------
       
   210 // IsHoldingEnabled
       
   211 // ----------------------------------------------------------------------------
       
   212 //
       
   213 TBool CGestureHelperImpl::IsDoubleTapEnabled() const
       
   214     {
       
   215     return iDoubleTapTimer->IsEnabled();
       
   216     }
       
   217     
       
   218 
       
   219 
       
   220 // ----------------------------------------------------------------------------
       
   221 // Reset state
       
   222 // ----------------------------------------------------------------------------
       
   223 //
       
   224 void CGestureHelperImpl::Reset()
       
   225     {
       
   226     iHoldingTimer->Cancel();
       
   227     iLongTouchTimer->Cancel();
       
   228     iGesture->Reset();
       
   229     }
       
   230 
       
   231 /** 
       
   232  * Helper function that calls Reset on the pointer to CGestureHelperImpl
       
   233  */
       
   234 static void ResetHelper( TAny* aHelper )
       
   235     {
       
   236     static_cast< CGestureHelperImpl* >( aHelper )->Reset();
       
   237     }
       
   238 
       
   239 // ----------------------------------------------------------------------------
       
   240 // Handle a pointer event
       
   241 // ----------------------------------------------------------------------------
       
   242 //
       
   243 TBool CGestureHelperImpl::HandlePointerEventL( const TPointerEvent& aEvent )
       
   244     {     
       
   245     TInt filterReason;
       
   246     SetLastEventTime();
       
   247     if (!iEventFilter->FilterDrag(aEvent, iLastEventTime, filterReason))
       
   248         {
       
   249         return noneAlf_HandlePointerEventL( aEvent );
       
   250         }
       
   251     else
       
   252         {
       
   253         /*
       
   254         TBuf<10> num;
       
   255         num.Num( filterReason );
       
   256         TBuf<128> str;
       
   257         str.AppendFormat(_L("Filter reason: %d"), filterReason);
       
   258         RFileLogger::Write( _L("gh"), _L("gh.txt"), EFileLoggingModeAppend, str);
       
   259         */
       
   260         return EFalse;
       
   261         }
       
   262     }
       
   263 
       
   264 
       
   265 TBool CGestureHelperImpl::noneAlf_HandlePointerEventL( const TPointerEvent& aEvent)
       
   266     {
       
   267     switch ( aEvent.iType )
       
   268         {
       
   269         case TPointerEvent::EButton1Down:
       
   270             {
       
   271             HandleTouchDownL(aEvent);
       
   272             break;
       
   273             }
       
   274         case TPointerEvent::EDrag:
       
   275             {
       
   276             HandleMoveL(aEvent);
       
   277             break;
       
   278             }
       
   279         case TPointerEvent::EButton1Up:
       
   280             {
       
   281             if (KErrNone == AddPoint( aEvent ))
       
   282                 {
       
   283                 HandleTouchUp(aEvent);
       
   284                 }
       
   285             else
       
   286                 {
       
   287                 EmitCancelEvent();
       
   288                 }
       
   289             Reset();
       
   290             break;
       
   291             }
       
   292         default:
       
   293             break;
       
   294         }
       
   295     return ETrue;
       
   296     }
       
   297 
       
   298 TBool CGestureHelperImpl::IsMovementGesture(TGestureCode aCode)
       
   299     {
       
   300     return (aCode == EGestureDrag || aCode == EGestureFlick || aCode == EGestureSwipeUp ||
       
   301             aCode == EGestureSwipeDown || aCode == EGestureSwipeRight || aCode == EGestureSwipeLeft);
       
   302     }
       
   303 
       
   304 void CGestureHelperImpl::HandleLongTouch()
       
   305     {
       
   306     iDoubleTapTimer->Cancel();
       
   307     iGesture->SetLongTap(ETrue);
       
   308     iGesture->SetComplete();
       
   309     TPoint startPos = iGesture->StartPos();
       
   310     EmitEvent(*iGesture);
       
   311     iGesture->Reset();
       
   312     iGesture->AddPoint( startPos, GetLastEventTime() );
       
   313     }
       
   314 
       
   315 void CGestureHelperImpl::HandleTouchDownL(const TPointerEvent& aEvent)
       
   316     {
       
   317     TGestureCode prevCode = iGesture->PreviousGestureCode();
       
   318     if (prevCode == EGestureStart) return;
       
   319     if (prevCode == EGestureDrag) 
       
   320         {
       
   321         iGesture->Reset();
       
   322         }
       
   323     AddPointL( aEvent );
       
   324     
       
   325     if (!iLongTouchTimer->IsActive())
       
   326         {
       
   327     iLongTouchTimer->Start();
       
   328         }
       
   329     if (!iDoubleTapTimer->IsActive())
       
   330         {
       
   331             EmitEvent( *iGesture );
       
   332         }
       
   333     }
       
   334 
       
   335 void CGestureHelperImpl::HandleMoveL(const TPointerEvent& aEvent)
       
   336     {
       
   337     if (iGesture->IsLatestPoint( Position(aEvent))) return; // I'm not sure we need this
       
   338     //Cancel double tap time - it's neither tap nor double tap 
       
   339     iDoubleTapTimer->Cancel();
       
   340     iLongTouchTimer->Cancel();
       
   341     
       
   342     TBool isFirstPoint = IsIdle();
       
   343     
       
   344     AddPointL( aEvent );
       
   345     
       
   346     if (iPreviousTapGesture)
       
   347         {
       
   348         RecycleGesture(iPreviousTapGesture);
       
   349         }
       
   350     
       
   351     if (!isFirstPoint)
       
   352         {
       
   353         EmitEvent( *iGesture );
       
   354         }
       
   355     }
       
   356 
       
   357 void CGestureHelperImpl::HandleTouchUp(const TPointerEvent& /*aEvent*/)
       
   358     {
       
   359     TGestureCode prevCode = iGesture->PreviousGestureCode();
       
   360     iLongTouchTimer->Cancel();
       
   361     iDoubleTapTimer->Cancel();
       
   362     TInt64 fromLastTouchUp = iLastEventTime.MicroSecondsFrom(iLastTouchUpTime).Int64();
       
   363     TInt64 fromLastDoubleTap = iLastEventTime.MicroSecondsFrom(iLastDoubleTapTime).Int64();
       
   364     /*
       
   365     TBuf<1024> str;
       
   366     str.AppendFormat(_L("fromLastTouchUp: %d, "), fromLastTouchUp);
       
   367     str.AppendFormat(_L("fromLastDoubleTap: %d, "), fromLastTouchUp);
       
   368     str.AppendFormat(_L("iPreviousTapGesture: %d, "), iPreviousTapGesture);
       
   369     RFileLogger::Write( _L("gh"), _L("gh.txt"), EFileLoggingModeAppend, str);
       
   370     */
       
   371     if ( prevCode == EGestureLongTap )
       
   372         {
       
   373         EmitReleasedEvent();
       
   374         }
       
   375     else if (IsMovementGesture(prevCode) || 
       
   376              !iDoubleTapTimer->IsEnabled() /* || !iGesture->IsTap()*/ ) 
       
   377         {
       
   378         iGesture->SetComplete();
       
   379         EmitEvent(*iGesture);
       
   380         }
       
   381     
       
   382     else 
       
   383         {
       
   384         if ( iPreviousTapGesture && 
       
   385          (fromLastTouchUp > KDoubleTapMinActivationInterval) &&       
       
   386          (fromLastTouchUp < KDoubleTapMaxActivationInterval) &&
       
   387          (fromLastDoubleTap > KDoubleTapIdleInterval))
       
   388             {
       
   389             // it's a double tap
       
   390             iLastTouchUpTime = iLastEventTime;
       
   391             iLastDoubleTapTime = iLastEventTime;
       
   392             EmitDoubleTapEvent();
       
   393             }
       
   394         else
       
   395             {
       
   396             // it's a first tap
       
   397             iLastTouchUpTime = iLastEventTime;
       
   398             if (iPreviousTapGesture)
       
   399                 {
       
   400                    RecycleGesture(iPreviousTapGesture);
       
   401                 }
       
   402                         
       
   403             iPreviousTapGesture = iGesture;
       
   404             iGesture = NewGesture();
       
   405             iDoubleTapTimer->Start(); 
       
   406             }
       
   407         }
       
   408     }
       
   409 
       
   410 
       
   411 
       
   412 void CGestureHelperImpl::EmitDoubleTapEvent()
       
   413     {
       
   414     iPreviousTapGesture->SetDoubleTap();
       
   415     EmitFirstTapEvent();
       
   416     }
       
   417 
       
   418 
       
   419 void CGestureHelperImpl::EmitReleasedEvent()
       
   420     {
       
   421     iGesture->SetComplete();
       
   422     iGesture->SetReleased();
       
   423     EmitEvent(*iGesture);
       
   424     }
       
   425 
       
   426 
       
   427 // ----------------------------------------------------------------------------
       
   428 // Is the helper idle?
       
   429 // inline ok in cpp file for a private member function
       
   430 // ----------------------------------------------------------------------------
       
   431 //
       
   432 inline TBool CGestureHelperImpl::IsIdle() const
       
   433     {
       
   434     return iGesture->IsEmpty();
       
   435     }
       
   436 
       
   437 // ----------------------------------------------------------------------------
       
   438 // Add a point to the sequence of points that together make up the gesture
       
   439 // inline ok in cpp file for a private member function
       
   440 // ----------------------------------------------------------------------------
       
   441 //
       
   442 inline void CGestureHelperImpl::AddPointL( const TPointerEvent& aEvent )
       
   443     {
       
   444     User::LeaveIfError( AddPoint( aEvent ) );
       
   445     }
       
   446 
       
   447 // ----------------------------------------------------------------------------
       
   448 // Add a point to the sequence of points that together make up the gesture
       
   449 // inline ok in cpp file for a private member function
       
   450 // ----------------------------------------------------------------------------
       
   451 //
       
   452 inline TInt CGestureHelperImpl::AddPoint( const TPointerEvent& aEvent )
       
   453     {
       
   454     TPoint pos = Position ( aEvent );
       
   455     return iGesture->AddPoint( pos, GetLastEventTime() );
       
   456     }
       
   457 
       
   458 // ----------------------------------------------------------------------------
       
   459 // StartHoldingTimer
       
   460 // ----------------------------------------------------------------------------
       
   461 //
       
   462 void CGestureHelperImpl::StartHoldingTimer( const TPointerEvent& aNewEvent )
       
   463     {
       
   464     if ( !( iGesture->IsHolding() ||
       
   465             iGesture->IsNearHoldingPoint( Position( aNewEvent ) ) ) )
       
   466         {
       
   467         // restart hold timer, since pointer has moved
       
   468         iHoldingTimer->Start();
       
   469         // Remember the point in which holding was started
       
   470         iGesture->SetHoldingPoint();
       
   471         }
       
   472     }
       
   473 
       
   474 /** 
       
   475  * Helper function that calls ContinueHolding on the pointer to TGesture
       
   476  */
       
   477 static void ContinueHolding( TAny* aGesture )
       
   478     {
       
   479     static_cast< CGesture* >( aGesture )->ContinueHolding();
       
   480     }
       
   481 
       
   482 // ----------------------------------------------------------------------------
       
   483 // Add a point to the sequence of points that together make up the gesture
       
   484 // ----------------------------------------------------------------------------
       
   485 //
       
   486 void CGestureHelperImpl::StartHoldingL()
       
   487     {
       
   488     // hold & tap event is specifically filtered out. Use case: in list fast 
       
   489     // scrolling activation (e.g. enhanced coverflow), tap & hold should not
       
   490     // start fast scroll. In addition, after long tap on start position,
       
   491     // drag and drag & hold swiping should emit normal swipe and swipe&hold
       
   492     // events. Therefore, tap & hold is not supported.
       
   493     __ASSERT_DEBUG( !iGesture->IsTap() && !iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) );
       
   494     
       
   495     // holding has just started, and gesture code should be provided to client.
       
   496     // set gesture state so that it produces a gesture code (other than drag)
       
   497     iGesture->StartHolding();
       
   498     
       
   499     // create an item in the cleanup stack that will set the gesture state
       
   500     // to holding-was-started-earlier state. NotifyL may leave, but the
       
   501     // holding-was-started-earlier state must still be successfully set,
       
   502     // otherwise, the holding gesture code will be sent twice
       
   503     CleanupStack::PushL( TCleanupItem( &ContinueHolding, iGesture ) );
       
   504     
       
   505     EmitEvent( *iGesture );
       
   506     
       
   507     // set holding state to "post holding"
       
   508     CleanupStack::PopAndDestroy( iGesture );
       
   509     }
       
   510 
       
   511 // ----------------------------------------------------------------------------
       
   512 // RecyclePreviousTapGesture
       
   513 // ----------------------------------------------------------------------------
       
   514 //
       
   515 void CGestureHelperImpl::RecyclePreviousTapGesture( TAny* aSelf )
       
   516     {
       
   517     CGestureHelperImpl& self = *reinterpret_cast<CGestureHelperImpl*>( aSelf );
       
   518     self.RecycleGesture( self.iPreviousTapGesture );
       
   519     }
       
   520 
       
   521 // ----------------------------------------------------------------------------
       
   522 // Emit the remainder of the previous tap event (tap + released)
       
   523 // ----------------------------------------------------------------------------
       
   524 //
       
   525 void CGestureHelperImpl::EmitFirstTapEvent()
       
   526     {
       
   527     // when this function is called, a tap has turned out to _not_ be a double tap
       
   528     __ASSERT_DEBUG( IsDoubleTapEnabled(), Panic( EGesturePanicIllegalLogic ) );
       
   529     __ASSERT_DEBUG( iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) );
       
   530     
       
   531     iDoubleTapTimer->Cancel();
       
   532     CompleteAndEmit( *iPreviousTapGesture );
       
   533     RecycleGesture(iPreviousTapGesture);
       
   534      
       
   535     }
       
   536 
       
   537 // ----------------------------------------------------------------------------
       
   538 // EmitStartEventL
       
   539 // ----------------------------------------------------------------------------
       
   540 //
       
   541 void CGestureHelperImpl::EmitStartEventL( const CGesture& aGesture )    
       
   542     {
       
   543     CGesture* startGesture = aGesture.AsStartEventLC();
       
   544     EmitEvent( *startGesture );
       
   545     CleanupStack::PopAndDestroy( startGesture );    
       
   546     }
       
   547     
       
   548 // ----------------------------------------------------------------------------
       
   549 // EmitCompletionEventsL
       
   550 // ----------------------------------------------------------------------------
       
   551 //
       
   552 void CGestureHelperImpl::CompleteAndEmit( CGesture& aGesture )
       
   553     {
       
   554     aGesture.SetComplete();
       
   555     // send gesture code if holding has not been started. If holding has 
       
   556     // been started, client has already received a "hold swipe left" e.g. event, in which
       
   557     // case don't another "swipe left" event
       
   558     if ( !aGesture.IsHolding() )
       
   559         {
       
   560         // if client leaves, the state is automatically reset.
       
   561         // In this case the client will not get the released event
       
   562         EmitEvent( aGesture ); 
       
   563         }
       
   564     
       
   565     // send an event that stylus was lifted
       
   566     aGesture.SetReleased();
       
   567     EmitEvent( aGesture ); 
       
   568     }
       
   569     
       
   570 // ----------------------------------------------------------------------------
       
   571 // EmitCancelEventL
       
   572 // ----------------------------------------------------------------------------
       
   573 //
       
   574 void CGestureHelperImpl::EmitCancelEvent()
       
   575     {
       
   576     iDoubleTapTimer->Cancel();
       
   577 
       
   578     
       
   579     CGesture& gestureToCancel = iPreviousTapGesture ? *iPreviousTapGesture : *iGesture;
       
   580     gestureToCancel.SetCancelled();
       
   581     EmitEvent( gestureToCancel );
       
   582     RecycleGesture(iPreviousTapGesture);
       
   583     
       
   584     }
       
   585 
       
   586 // ----------------------------------------------------------------------------
       
   587 // Notify observer
       
   588 // ----------------------------------------------------------------------------
       
   589 //
       
   590 void CGestureHelperImpl::EmitEvent( const CGesture& aGesture )
       
   591     {
       
   592     // deallocation of the event is happening in CGestureEventSender::RunL() 
       
   593     TGestureEvent event;
       
   594     event.SetCode(const_cast<CGesture&>(aGesture).Code(EAxisBoth));
       
   595     event.SetCurrentPos(aGesture.CurrentPos());
       
   596     event.SetDistance(aGesture.Distance());
       
   597     event.SetStartPos(aGesture.StartPos());
       
   598     event.SetIsHolding(aGesture.IsHolding());
       
   599     event.SetSpeed(aGesture.Speed());
       
   600     iEventSender->AddEvent(event);
       
   601     }
       
   602 
       
   603 // ----------------------------------------------------------------------------
       
   604 // Return a fresh gesture from the gesture pool (pool of one gesture)
       
   605 // ----------------------------------------------------------------------------
       
   606 //
       
   607 CGesture* CGestureHelperImpl::NewGesture()
       
   608     {
       
   609     __ASSERT_DEBUG( iUnusedGesture, Panic( EGesturePanicIllegalLogic ) ); // pool should no be empty
       
   610     
       
   611     iUnusedGesture->Reset();
       
   612     CGesture* freshGesture = iUnusedGesture;
       
   613     iUnusedGesture = NULL;
       
   614     return freshGesture;
       
   615     }
       
   616 
       
   617 // ----------------------------------------------------------------------------
       
   618 // Return a fresh gesture from the gesture pool (pool of one gesture)
       
   619 // ----------------------------------------------------------------------------
       
   620 //
       
   621 void CGestureHelperImpl::RecycleGesture( CGesture*& aGesturePointer )
       
   622     {
       
   623     // only one object fits into the pool, and that should currently be enough
       
   624     // one pointer must be null, one non-null
       
   625     __ASSERT_DEBUG( !iUnusedGesture != !aGesturePointer, Panic( EGesturePanicIllegalLogic ) );
       
   626     if ( aGesturePointer )
       
   627         {
       
   628         iUnusedGesture = aGesturePointer;
       
   629         aGesturePointer = NULL;
       
   630         }
       
   631     }