webengine/webkitutils/rt_gesturehelper/src/gesturehelperimpl.cpp
changeset 1 7c90e6132015
parent 0 dd21522fd290
equal deleted inserted replaced
0:dd21522fd290 1:7c90e6132015
    16 */
    16 */
    17 
    17 
    18 
    18 
    19 #include "gesturehelperimpl.h"
    19 #include "gesturehelperimpl.h"
    20 
    20 
    21 #include <alf/alfevent.h>
       
    22 #include <e32base.h>
    21 #include <e32base.h>
    23 #include <w32std.h>
    22 #include <w32std.h>
    24 
    23 
    25 #include "gesture.h"
    24 #include "gesture.h"
    26 #include "gesturedefs.h"
    25 #include "gesturedefs.h"
    27 #include "utils.h"
    26 #include "utils.h"
    28 #include "pointercapturer.h"
       
    29 #include "gestureeventfilter.h"
    27 #include "gestureeventfilter.h"
    30 #include "gesturehelpereventsender.h"
    28 #include "gesturehelpereventsender.h"
    31 #include "flogger.h"
    29 #include "flogger.h"
    32 #include "gestureevent.h"
       
    33 
    30 
    34 using namespace RT_GestureHelper;
    31 using namespace RT_GestureHelper;
    35 
    32 
    36 namespace RT_GestureHelper
    33 namespace RT_GestureHelper
    37 {
    34 {
   126     {
   123     {
   127     // use parent position, since the capturer is using full screen area,
   124     // use parent position, since the capturer is using full screen area,
   128     // and because the (Alfred) drag events are not local to visual even when
   125     // and because the (Alfred) drag events are not local to visual even when
   129     // coming from the client
   126     // coming from the client
   130     
   127     
   131     return aEvent.iParentPosition;
   128     return aEvent.iPosition;
   132     }
   129     }
   133 
   130 
   134 // ----------------------------------------------------------------------------
   131 // ----------------------------------------------------------------------------
   135 // Two-phase constructor
   132 // Two-phase constructor
   136 // ----------------------------------------------------------------------------
   133 // ----------------------------------------------------------------------------
   138 CGestureHelperImpl* CGestureHelperImpl::NewL( MGestureObserver& aObserver )
   135 CGestureHelperImpl* CGestureHelperImpl::NewL( MGestureObserver& aObserver )
   139     {
   136     {
   140     CGestureHelperImpl* self = new ( ELeave ) CGestureHelperImpl( aObserver );
   137     CGestureHelperImpl* self = new ( ELeave ) CGestureHelperImpl( aObserver );
   141     CleanupStack::PushL( self );
   138     CleanupStack::PushL( self );
   142     self->iEventSender = CGestureEventSender::NewL( aObserver );
   139     self->iEventSender = CGestureEventSender::NewL( aObserver );
   143     self->iDoubleTapTimer = CCallbackTimer::NewL( *self, EmitFirstTapEventL, 
   140     self->iDoubleTapTimer = CCallbackTimer::NewL( *self, EmitFirstTapEvent, 
   144             KMaxTapDuration, EFalse ); // double tap is disabled by default
   141             KMaxTapDuration, EFalse ); // double tap is disabled by default
   145     self->iHoldingTimer = CCallbackTimer::NewL( *self, StartHoldingL, 
   142     self->iHoldingTimer = CCallbackTimer::NewL( *self, StartHoldingL, 
   146         KHoldDuration, EFalse ); // holding is enabled by default
   143         KHoldDuration, EFalse ); // holding is enabled by default
   147     
   144     
   148     self->iLongTouchTimer = CCallbackTimer::NewL( *self, HandleLongTouchL, 
   145     self->iLongTouchTimer = CCallbackTimer::NewL( *self, HandleLongTouch, 
   149             KLongTapDuration, ETrue ); // holding is enabled by default
   146             KLongTapDuration, ETrue ); // holding is enabled by default
   150     self->iPointerCapturer = CPointerCapturer::NewL();    
   147     
   151     self->iGesture = new ( ELeave ) CGesture();
   148     self->iGesture = new ( ELeave ) CGesture();
   152     self->iUnusedGesture = new ( ELeave ) CGesture();
   149     self->iUnusedGesture = new ( ELeave ) CGesture();
   153     TInt tapLimit = Mm2Pixels(KFingerSize_mm) / 2;
   150     TInt tapLimit = Mm2Pixels(KFingerSize_mm) / 2;
   154     self->iEventFilter = new (ELeave) CGestureEventFilter(tapLimit);
   151     self->iEventFilter = new (ELeave) CGestureEventFilter(tapLimit);
   155     CleanupStack::Pop( self );
   152     CleanupStack::Pop( self );
   174     delete iDoubleTapTimer;
   171     delete iDoubleTapTimer;
   175     delete iHoldingTimer;
   172     delete iHoldingTimer;
   176     delete iGesture;
   173     delete iGesture;
   177     delete iPreviousTapGesture;
   174     delete iPreviousTapGesture;
   178     delete iUnusedGesture;
   175     delete iUnusedGesture;
   179     delete iPointerCapturer;
       
   180     delete iLongTouchTimer;
   176     delete iLongTouchTimer;
   181     delete iEventFilter;
   177     delete iEventFilter;
   182     delete iEventSender;
   178     delete iEventSender;
   183     }
   179     }
   184     
   180     
   217 TBool CGestureHelperImpl::IsDoubleTapEnabled() const
   213 TBool CGestureHelperImpl::IsDoubleTapEnabled() const
   218     {
   214     {
   219     return iDoubleTapTimer->IsEnabled();
   215     return iDoubleTapTimer->IsEnabled();
   220     }
   216     }
   221     
   217     
   222 // ----------------------------------------------------------------------------
   218 
   223 // InitAlfredPointerEventCaptureL
       
   224 // ----------------------------------------------------------------------------
       
   225 //
       
   226 void CGestureHelperImpl::InitAlfredPointerCaptureL( CAlfEnv& aEnv, 
       
   227         CAlfDisplay& aDisplay, TInt aFreeControlGroupId )
       
   228     {
       
   229     iPointerCapturer->InitForAlfredL(*this, aEnv, aDisplay, aFreeControlGroupId );
       
   230     }
       
   231 
   219 
   232 // ----------------------------------------------------------------------------
   220 // ----------------------------------------------------------------------------
   233 // Reset state
   221 // Reset state
   234 // ----------------------------------------------------------------------------
   222 // ----------------------------------------------------------------------------
   235 //
   223 //
   236 void CGestureHelperImpl::Reset()
   224 void CGestureHelperImpl::Reset()
   237     {
   225     {
   238     iHoldingTimer->Cancel();
   226     iHoldingTimer->Cancel();
   239     iLongTouchTimer->Cancel();
   227     iLongTouchTimer->Cancel();
   240     iGesture->Reset();
   228     iGesture->Reset();
   241     iPointerCapturer->Stop();
       
   242     }
   229     }
   243 
   230 
   244 /** 
   231 /** 
   245  * Helper function that calls Reset on the pointer to CGestureHelperImpl
   232  * Helper function that calls Reset on the pointer to CGestureHelperImpl
   246  */
   233  */
   257     {     
   244     {     
   258     TInt filterReason;
   245     TInt filterReason;
   259     SetLastEventTime();
   246     SetLastEventTime();
   260     if (!iEventFilter->FilterDrag(aEvent, iLastEventTime, filterReason))
   247     if (!iEventFilter->FilterDrag(aEvent, iLastEventTime, filterReason))
   261         {
   248         {
   262         iGesture->SetVisual( NULL );
       
   263         return noneAlf_HandlePointerEventL( aEvent );
   249         return noneAlf_HandlePointerEventL( aEvent );
   264         }
   250         }
   265     else
   251     else
   266         {
   252         {
   267         /*
   253         /*
   273         */
   259         */
   274         return EFalse;
   260         return EFalse;
   275         }
   261         }
   276     }
   262     }
   277 
   263 
   278 // ----------------------------------------------------------------------------
       
   279 // OfferEventL
       
   280 // ----------------------------------------------------------------------------
       
   281 //
       
   282 TBool CGestureHelperImpl::OfferEventL( const TAlfEvent& aEvent )
       
   283     {
       
   284     if ( aEvent.IsPointerEvent() )
       
   285         {
       
   286         return HandlePointerEventL( aEvent.PointerEvent(), aEvent.Visual() );
       
   287         }
       
   288     return EFalse;
       
   289     }
       
   290 
       
   291 
       
   292 
       
   293 
       
   294 
       
   295 
       
   296 // ----------------------------------------------------------------------------
       
   297 // Handle a pointer event
       
   298 // ----------------------------------------------------------------------------
       
   299 //
       
   300 
       
   301 
   264 
   302 TBool CGestureHelperImpl::noneAlf_HandlePointerEventL( const TPointerEvent& aEvent)
   265 TBool CGestureHelperImpl::noneAlf_HandlePointerEventL( const TPointerEvent& aEvent)
   303     {
   266     {
   304     
       
   305     switch ( aEvent.iType )
   267     switch ( aEvent.iType )
   306         {
   268         {
   307         case TPointerEvent::EButton1Down:
   269         case TPointerEvent::EButton1Down:
   308             {
   270             {
   309             
       
   310             iPointerCapturer->StartL();
       
   311             HandleTouchDownL(aEvent);
   271             HandleTouchDownL(aEvent);
   312             break;
   272             break;
   313             }
   273             }
   314         case TPointerEvent::EDrag:
   274         case TPointerEvent::EDrag:
   315             {
   275             {
   316             HandleMoveL(aEvent);
   276             HandleMoveL(aEvent);
   317             break;
   277             break;
   318             }
   278             }
   319         case TPointerEvent::EButton1Up:
   279         case TPointerEvent::EButton1Up:
   320             {
   280             {
   321             CleanupStack::PushL( TCleanupItem( &ResetHelper, this ) );
       
   322             if (KErrNone == AddPoint( aEvent ))
   281             if (KErrNone == AddPoint( aEvent ))
   323                 {
   282                 {
   324                 HandleTouchUpL(aEvent);
   283                 HandleTouchUp(aEvent);
   325                 }
   284                 }
   326             else
   285             else
   327                 {
   286                 {
   328                 EmitCancelEventL();
   287                 EmitCancelEvent();
   329                 }
   288                 }
   330             CleanupStack::PopAndDestroy( this ); 
   289             Reset();
   331             break;
   290             break;
   332             }
   291             }
   333         default:
   292         default:
   334             break;
   293             break;
   335         }
   294         }
   336     return ETrue;
   295     return ETrue;
   337     }
   296     }
   338 
   297 
   339 
       
   340 TBool CGestureHelperImpl::HandlePointerEventL( const TPointerEvent& aEvent,
       
   341         CAlfVisual* aVisual )
       
   342     {  
       
   343     // filter out events that do not start with button down. It is a stray
       
   344     // event from another visual
       
   345     if ( IsIdle() && aEvent.iType != TPointerEvent::EButton1Down )
       
   346         {
       
   347         return EFalse; // don't consume
       
   348         }
       
   349     
       
   350     switch ( aEvent.iType )
       
   351         {
       
   352         case TPointerEvent::EButton1Down:
       
   353             // If no up event was received during previous gesture, cancel 
       
   354             // previous event and reset state
       
   355             if ( !IsIdle() )
       
   356                 {
       
   357                 // ambiguous what is the right thing when "cancel" event leaves
       
   358                 // and "start" does not. Leaving for cancel *after* "start" could 
       
   359                 // be unexpected to client, as client would have handled start 
       
   360                 // event successfully. Assume that leaving upon cancellation 
       
   361                 // can be ignored.
       
   362                 TRAP_IGNORE( EmitCancelEventL() );
       
   363                 Reset();  
       
   364                 }
       
   365             // as long as down event of a double tap comes within the double 
       
   366             // tap timeout, it does not matter how long the user keeps the finger
       
   367             // pressed for the gesture to be a double tap. Therefore, cancel
       
   368             // the timeout, as it is no longer relevant. (Of course, this call
       
   369             // will only do something if the timer is actually running, which
       
   370             // is only if received a tap event very recently.)
       
   371             iDoubleTapTimer->Cancel();
       
   372             // adding the first point implicitly makes the state "not idle"
       
   373             AddPointL( aEvent );
       
   374             iGesture->SetVisual( aVisual );
       
   375             // if pointer capturer leaves, the remaining pointer events will
       
   376             // not be captured if stylus is dragged outside the capturing visual
       
   377             // an error note will be shown, so the potential problem is irrelevant,
       
   378             // assuming client does not (incorrectly) block the leave from reaching 
       
   379             // the framework
       
   380             iPointerCapturer->StartL();
       
   381             // Delay emitting a down event _until_ it is known that this beginning 
       
   382             // gesture is _not_ the second tap of a double tap event.
       
   383             // iPreviousTapGesture is only non-null if very recently received 
       
   384             // a tap event and double tap is enabled. 
       
   385             if ( !iPreviousTapGesture )
       
   386                 {
       
   387                 EmitEventL( *iGesture );
       
   388                 }
       
   389             // else delay emitting an event, as it might be a double tap 
       
   390             // (allow the second tap of a double tap to be anywhere, so don't check
       
   391             // for start pos here)
       
   392             break;
       
   393             
       
   394         case TPointerEvent::EDrag:
       
   395             // While stylus down, the same event is received repeatedly
       
   396             // even if stylus does not move. Filter out by checking if point 
       
   397             // is the same as the latest point
       
   398             if ( !iGesture->IsLatestPoint( Position( aEvent ) ) )
       
   399                 {
       
   400                 AddPointL( aEvent );
       
   401 
       
   402                 // as long as the starting gesture is seen as a tap, do not emit any
       
   403                 // drag events
       
   404                 if ( !iGesture->IsTap() )
       
   405                     {
       
   406                     // if there is a previous tap gesture, getting drag events means that
       
   407                     // the previous gesture is not a double tap. So emit the previous gesture.
       
   408                     if ( iPreviousTapGesture )
       
   409                         {
       
   410                         // this is a second gesture after a tap (double tap is enabled)
       
   411                         EmitFirstTapEventL();
       
   412                         // emit down event for the current gesture (since its down was delayed, until
       
   413                         // it was to be known if the event is a tap. That is known now.)
       
   414                         EmitStartEventL( *iGesture );
       
   415                         }
       
   416                     // restart holding timer every time the current stylus pos changes
       
   417                     StartHoldingTimer( aEvent );
       
   418                     // emit the drag event to client
       
   419                     EmitEventL( *iGesture );
       
   420                     }
       
   421                 // else: do not emit drag events until it is known that the gesture is not a tap
       
   422                 // (or the second tap of double tap)
       
   423                 }
       
   424             break;
       
   425 
       
   426         case TPointerEvent::EButton1Up:
       
   427             // reset in case the down event for next gesture is not received for a reason 
       
   428             // in client, and instead drag or up events are received. 
       
   429             // reset via cleanup stack to ensure Reset is run even if
       
   430             // observer leaves
       
   431             CleanupStack::PushL( TCleanupItem( &ResetHelper, this ) );
       
   432             // if adding of the point fails, notify client with a 
       
   433             // cancelled event. It would be wrong to send another
       
   434             // gesture code when the up point is not known
       
   435             if ( KErrNone == AddPoint( aEvent ) )
       
   436                 {
       
   437                 
       
   438                 // if the gesture is a tap, the gesture is either the first tap of a _potential_
       
   439                 // double tap, or the second tap of a double tap
       
   440                 if ( iDoubleTapTimer->IsEnabled() && iGesture->IsTap() )
       
   441                     {
       
   442                     __ASSERT_DEBUG( !iGesture->IsHolding(), Panic( EGesturePanicIllegalLogic ) );
       
   443                     if ( !iPreviousTapGesture )
       
   444                         {
       
   445                         // First tap. Delay emitting its code evemt and released events until it is known
       
   446                         // whether the tap is a double tap
       
   447                         iPreviousTapGesture = iGesture;
       
   448                         iGesture = NewGesture();
       
   449                         iDoubleTapTimer->Start(); 
       
   450                         }
       
   451                     else
       
   452                         {
       
   453                         // This is a second tap of a double tap. Do not emit anything for the second
       
   454                         // tap. Only down event has been emitted for the first tap. Emit the code 
       
   455                         // event (double tap) and released for the first tap.
       
   456                         iPreviousTapGesture->SetDoubleTap();
       
   457                         EmitFirstTapEventL();
       
   458                         }
       
   459                     }
       
   460                 
       
   461                 else 
       
   462                     {
       
   463                     // modified iGesture to be "released"
       
   464                     CompleteAndEmitL( *iGesture );
       
   465                     }
       
   466                 }
       
   467             else
       
   468                 { // adding a point failed
       
   469                 EmitCancelEventL();
       
   470                 }
       
   471             // reset state
       
   472             CleanupStack::PopAndDestroy( this ); 
       
   473             break;
       
   474             
       
   475         default:
       
   476             break;
       
   477         }
       
   478     return ETrue; // consume
       
   479     }
       
   480 
       
   481 
       
   482 TBool CGestureHelperImpl::IsMovementGesture(TGestureCode aCode)
   298 TBool CGestureHelperImpl::IsMovementGesture(TGestureCode aCode)
   483     {
   299     {
   484     return (aCode == EGestureDrag || aCode == EGestureFlick || aCode == EGestureSwipeUp ||
   300     return (aCode == EGestureDrag || aCode == EGestureFlick || aCode == EGestureSwipeUp ||
   485             aCode == EGestureSwipeDown || aCode == EGestureSwipeRight || aCode == EGestureSwipeLeft);
   301             aCode == EGestureSwipeDown || aCode == EGestureSwipeRight || aCode == EGestureSwipeLeft);
   486     }
   302     }
   487 
   303 
   488 void CGestureHelperImpl::HandleLongTouchL()
   304 void CGestureHelperImpl::HandleLongTouch()
   489     {
   305     {
   490     iDoubleTapTimer->Cancel();
   306     iDoubleTapTimer->Cancel();
   491     iGesture->SetLongTap(ETrue);
   307     iGesture->SetLongTap(ETrue);
   492     iGesture->SetComplete();
   308     iGesture->SetComplete();
   493     TPoint startPos = iGesture->StartPos();
   309     TPoint startPos = iGesture->StartPos();
   494     EmitEventL(*iGesture);
   310     EmitEvent(*iGesture);
   495     iGesture->Reset();
   311     iGesture->Reset();
   496     iGesture->AddPoint( startPos, GetLastEventTime() );
   312     iGesture->AddPoint( startPos, GetLastEventTime() );
   497     }
   313     }
   498 
   314 
   499 void CGestureHelperImpl::HandleTouchDownL(const TPointerEvent& aEvent)
   315 void CGestureHelperImpl::HandleTouchDownL(const TPointerEvent& aEvent)
   500     {
   316     {
   501     TGestureCode prevCode = iGesture->PreviousGestureCode();
   317     TGestureCode prevCode = iGesture->PreviousGestureCode();
   502     if (prevCode == EGestureStart) return;
   318     if (prevCode == EGestureStart) return;
       
   319     if (prevCode == EGestureDrag) 
       
   320         {
       
   321         iGesture->Reset();
       
   322         }
   503     AddPointL( aEvent );
   323     AddPointL( aEvent );
   504     
   324     
       
   325     if (!iLongTouchTimer->IsActive())
       
   326         {
   505     iLongTouchTimer->Start();
   327     iLongTouchTimer->Start();
       
   328         }
   506     if (!iDoubleTapTimer->IsActive())
   329     if (!iDoubleTapTimer->IsActive())
   507         {
   330         {
   508             EmitEventL( *iGesture );
   331             EmitEvent( *iGesture );
   509         }
   332         }
   510     }
   333     }
   511 
   334 
   512 void CGestureHelperImpl::HandleMoveL(const TPointerEvent& aEvent)
   335 void CGestureHelperImpl::HandleMoveL(const TPointerEvent& aEvent)
   513     {
   336     {
   514     if (iGesture->IsLatestPoint( iGesture->Visual() ? Position ( aEvent ) : aEvent.iPosition)) return; // I'm not sure we need this
   337     if (iGesture->IsLatestPoint( Position(aEvent))) return; // I'm not sure we need this
   515     //Cancel double tap time - it's neither tap nor double tap 
   338     //Cancel double tap time - it's neither tap nor double tap 
   516     iDoubleTapTimer->Cancel();
   339     iDoubleTapTimer->Cancel();
   517     iLongTouchTimer->Cancel();
   340     iLongTouchTimer->Cancel();
   518     
   341     
   519     TBool isFirstPoint = IsIdle();
   342     TBool isFirstPoint = IsIdle();
   525         RecycleGesture(iPreviousTapGesture);
   348         RecycleGesture(iPreviousTapGesture);
   526         }
   349         }
   527     
   350     
   528     if (!isFirstPoint)
   351     if (!isFirstPoint)
   529         {
   352         {
   530         EmitEventL( *iGesture );
   353         EmitEvent( *iGesture );
   531         }
   354         }
   532     }
   355     }
   533 
   356 
   534 void CGestureHelperImpl::HandleTouchUpL(const TPointerEvent& /*aEvent*/)
   357 void CGestureHelperImpl::HandleTouchUp(const TPointerEvent& /*aEvent*/)
   535     {
   358     {
   536     TGestureCode prevCode = iGesture->PreviousGestureCode();
   359     TGestureCode prevCode = iGesture->PreviousGestureCode();
   537     iLongTouchTimer->Cancel();
   360     iLongTouchTimer->Cancel();
   538     iDoubleTapTimer->Cancel();
   361     iDoubleTapTimer->Cancel();
   539     TInt64 fromLastTouchUp = iLastEventTime.MicroSecondsFrom(iLastTouchUpTime).Int64();
   362     TInt64 fromLastTouchUp = iLastEventTime.MicroSecondsFrom(iLastTouchUpTime).Int64();
   545     str.AppendFormat(_L("iPreviousTapGesture: %d, "), iPreviousTapGesture);
   368     str.AppendFormat(_L("iPreviousTapGesture: %d, "), iPreviousTapGesture);
   546     RFileLogger::Write( _L("gh"), _L("gh.txt"), EFileLoggingModeAppend, str);
   369     RFileLogger::Write( _L("gh"), _L("gh.txt"), EFileLoggingModeAppend, str);
   547     */
   370     */
   548     if ( prevCode == EGestureLongTap )
   371     if ( prevCode == EGestureLongTap )
   549         {
   372         {
   550         EmitReleasedEventL();
   373         EmitReleasedEvent();
   551         }
   374         }
   552     else if (IsMovementGesture(prevCode) || 
   375     else if (IsMovementGesture(prevCode) || 
   553              !iDoubleTapTimer->IsEnabled() /* || !iGesture->IsTap()*/ ) 
   376              !iDoubleTapTimer->IsEnabled() /* || !iGesture->IsTap()*/ ) 
   554         {
   377         {
   555         iGesture->SetComplete();
   378         iGesture->SetComplete();
   556         EmitEventL(*iGesture);
   379         EmitEvent(*iGesture);
   557         }
   380         }
   558     
   381     
   559     else 
   382     else 
   560         {
   383         {
   561         if ( iPreviousTapGesture && 
   384         if ( iPreviousTapGesture && 
   564          (fromLastDoubleTap > KDoubleTapIdleInterval))
   387          (fromLastDoubleTap > KDoubleTapIdleInterval))
   565             {
   388             {
   566             // it's a double tap
   389             // it's a double tap
   567             iLastTouchUpTime = iLastEventTime;
   390             iLastTouchUpTime = iLastEventTime;
   568             iLastDoubleTapTime = iLastEventTime;
   391             iLastDoubleTapTime = iLastEventTime;
   569             EmitDoubleTapEventL();
   392             EmitDoubleTapEvent();
   570             }
   393             }
   571         else
   394         else
   572             {
   395             {
   573             // it's a first tap
   396             // it's a first tap
   574             iLastTouchUpTime = iLastEventTime;
   397             iLastTouchUpTime = iLastEventTime;
   584         }
   407         }
   585     }
   408     }
   586 
   409 
   587 
   410 
   588 
   411 
   589 void CGestureHelperImpl::EmitDoubleTapEventL()
   412 void CGestureHelperImpl::EmitDoubleTapEvent()
   590     {
   413     {
   591     iPreviousTapGesture->SetDoubleTap();
   414     iPreviousTapGesture->SetDoubleTap();
   592     EmitFirstTapEventL();
   415     EmitFirstTapEvent();
   593     }
   416     }
   594 
   417 
   595 
   418 
   596 void CGestureHelperImpl::EmitReleasedEventL()
   419 void CGestureHelperImpl::EmitReleasedEvent()
   597     {
   420     {
   598     iGesture->SetComplete();
   421     iGesture->SetComplete();
   599     iGesture->SetReleased();
   422     iGesture->SetReleased();
   600     EmitEventL(*iGesture);
   423     EmitEvent(*iGesture);
   601     }
   424     }
   602 
   425 
   603 
   426 
   604 // ----------------------------------------------------------------------------
   427 // ----------------------------------------------------------------------------
   605 // Is the helper idle?
   428 // Is the helper idle?
   626 // inline ok in cpp file for a private member function
   449 // inline ok in cpp file for a private member function
   627 // ----------------------------------------------------------------------------
   450 // ----------------------------------------------------------------------------
   628 //
   451 //
   629 inline TInt CGestureHelperImpl::AddPoint( const TPointerEvent& aEvent )
   452 inline TInt CGestureHelperImpl::AddPoint( const TPointerEvent& aEvent )
   630     {
   453     {
   631     TPoint pos = iGesture->Visual() ? Position ( aEvent ) : aEvent.iPosition;
   454     TPoint pos = Position ( aEvent );
   632     return iGesture->AddPoint( pos, GetLastEventTime() );
   455     return iGesture->AddPoint( pos, GetLastEventTime() );
   633     }
   456     }
   634 
   457 
   635 // ----------------------------------------------------------------------------
   458 // ----------------------------------------------------------------------------
   636 // StartHoldingTimer
   459 // StartHoldingTimer
   677     // to holding-was-started-earlier state. NotifyL may leave, but the
   500     // to holding-was-started-earlier state. NotifyL may leave, but the
   678     // holding-was-started-earlier state must still be successfully set,
   501     // holding-was-started-earlier state must still be successfully set,
   679     // otherwise, the holding gesture code will be sent twice
   502     // otherwise, the holding gesture code will be sent twice
   680     CleanupStack::PushL( TCleanupItem( &ContinueHolding, iGesture ) );
   503     CleanupStack::PushL( TCleanupItem( &ContinueHolding, iGesture ) );
   681     
   504     
   682     EmitEventL( *iGesture );
   505     EmitEvent( *iGesture );
   683     
   506     
   684     // set holding state to "post holding"
   507     // set holding state to "post holding"
   685     CleanupStack::PopAndDestroy( iGesture );
   508     CleanupStack::PopAndDestroy( iGesture );
   686     }
   509     }
   687 
   510 
   697 
   520 
   698 // ----------------------------------------------------------------------------
   521 // ----------------------------------------------------------------------------
   699 // Emit the remainder of the previous tap event (tap + released)
   522 // Emit the remainder of the previous tap event (tap + released)
   700 // ----------------------------------------------------------------------------
   523 // ----------------------------------------------------------------------------
   701 //
   524 //
   702 void CGestureHelperImpl::EmitFirstTapEventL()
   525 void CGestureHelperImpl::EmitFirstTapEvent()
   703     {
   526     {
   704     // when this function is called, a tap has turned out to _not_ be a double tap
   527     // when this function is called, a tap has turned out to _not_ be a double tap
   705     __ASSERT_DEBUG( IsDoubleTapEnabled(), Panic( EGesturePanicIllegalLogic ) );
   528     __ASSERT_DEBUG( IsDoubleTapEnabled(), Panic( EGesturePanicIllegalLogic ) );
   706     __ASSERT_DEBUG( iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) );
   529     __ASSERT_DEBUG( iPreviousTapGesture, Panic( EGesturePanicIllegalLogic ) );
   707     
   530     
   708     iDoubleTapTimer->Cancel();
   531     iDoubleTapTimer->Cancel();
   709     
   532     CompleteAndEmit( *iPreviousTapGesture );
   710     // ensure previous tap gesture is reset even if client leaves
   533     RecycleGesture(iPreviousTapGesture);
   711     CleanupStack::PushL( TCleanupItem( &RecyclePreviousTapGesture, this ) );
   534      
   712     
       
   713     CompleteAndEmitL( *iPreviousTapGesture );
       
   714     
       
   715     // recycle the emitted gesture 
       
   716     CleanupStack::PopAndDestroy( this ); 
       
   717     }
   535     }
   718 
   536 
   719 // ----------------------------------------------------------------------------
   537 // ----------------------------------------------------------------------------
   720 // EmitStartEventL
   538 // EmitStartEventL
   721 // ----------------------------------------------------------------------------
   539 // ----------------------------------------------------------------------------
   722 //
   540 //
   723 void CGestureHelperImpl::EmitStartEventL( const CGesture& aGesture )    
   541 void CGestureHelperImpl::EmitStartEventL( const CGesture& aGesture )    
   724     {
   542     {
   725     CGesture* startGesture = aGesture.AsStartEventLC();
   543     CGesture* startGesture = aGesture.AsStartEventLC();
   726     EmitEventL( *startGesture );
   544     EmitEvent( *startGesture );
   727     CleanupStack::PopAndDestroy( startGesture );    
   545     CleanupStack::PopAndDestroy( startGesture );    
   728     }
   546     }
   729     
   547     
   730 // ----------------------------------------------------------------------------
   548 // ----------------------------------------------------------------------------
   731 // EmitCompletionEventsL
   549 // EmitCompletionEventsL
   732 // ----------------------------------------------------------------------------
   550 // ----------------------------------------------------------------------------
   733 //
   551 //
   734 void CGestureHelperImpl::CompleteAndEmitL( CGesture& aGesture )
   552 void CGestureHelperImpl::CompleteAndEmit( CGesture& aGesture )
   735     {
   553     {
   736     aGesture.SetComplete();
   554     aGesture.SetComplete();
   737     // send gesture code if holding has not been started. If holding has 
   555     // send gesture code if holding has not been started. If holding has 
   738     // been started, client has already received a "hold swipe left" e.g. event, in which
   556     // been started, client has already received a "hold swipe left" e.g. event, in which
   739     // case don't another "swipe left" event
   557     // case don't another "swipe left" event
   740     if ( !aGesture.IsHolding() )
   558     if ( !aGesture.IsHolding() )
   741         {
   559         {
   742         // if client leaves, the state is automatically reset.
   560         // if client leaves, the state is automatically reset.
   743         // In this case the client will not get the released event
   561         // In this case the client will not get the released event
   744         EmitEventL( aGesture ); 
   562         EmitEvent( aGesture ); 
   745         }
   563         }
   746     
   564     
   747     // send an event that stylus was lifted
   565     // send an event that stylus was lifted
   748     aGesture.SetReleased();
   566     aGesture.SetReleased();
   749     EmitEventL( aGesture ); 
   567     EmitEvent( aGesture ); 
   750     }
   568     }
   751     
   569     
   752 // ----------------------------------------------------------------------------
   570 // ----------------------------------------------------------------------------
   753 // EmitCancelEventL
   571 // EmitCancelEventL
   754 // ----------------------------------------------------------------------------
   572 // ----------------------------------------------------------------------------
   755 //
   573 //
   756 void CGestureHelperImpl::EmitCancelEventL()
   574 void CGestureHelperImpl::EmitCancelEvent()
   757     {
   575     {
   758     iDoubleTapTimer->Cancel();
   576     iDoubleTapTimer->Cancel();
   759 
   577 
   760     // ensure previous tap gesture is reset even if client leaves
   578     
   761     CleanupStack::PushL( TCleanupItem( &RecyclePreviousTapGesture, this ) );
       
   762 
       
   763     CGesture& gestureToCancel = iPreviousTapGesture ? *iPreviousTapGesture : *iGesture;
   579     CGesture& gestureToCancel = iPreviousTapGesture ? *iPreviousTapGesture : *iGesture;
   764     gestureToCancel.SetCancelled();
   580     gestureToCancel.SetCancelled();
   765     EmitEventL( gestureToCancel );
   581     EmitEvent( gestureToCancel );
   766     
   582     RecycleGesture(iPreviousTapGesture);
   767     // recycle the emitted gesture 
   583     
   768     CleanupStack::PopAndDestroy( this ); 
       
   769     }
   584     }
   770 
   585 
   771 // ----------------------------------------------------------------------------
   586 // ----------------------------------------------------------------------------
   772 // Notify observer
   587 // Notify observer
   773 // ----------------------------------------------------------------------------
   588 // ----------------------------------------------------------------------------
   774 //
   589 //
   775 void CGestureHelperImpl::EmitEventL( const CGesture& aGesture )
   590 void CGestureHelperImpl::EmitEvent( const CGesture& aGesture )
   776     {
   591     {
   777     // deallocation of the event is happening in CGestureEventSender::RunL() 
   592     // deallocation of the event is happening in CGestureEventSender::RunL() 
   778     CGestureEvent* event = new(ELeave) CGestureEvent();
   593     TGestureEvent event;
   779     event->iCode = const_cast<CGesture&>(aGesture).Code(MGestureEvent::EAxisBoth);
   594     event.SetCode(const_cast<CGesture&>(aGesture).Code(EAxisBoth));
   780     event->iCurrPos = aGesture.CurrentPos();
   595     event.SetCurrentPos(aGesture.CurrentPos());
   781     event->iDistance = aGesture.Distance();
   596     event.SetDistance(aGesture.Distance());
   782     event->iStartPos = aGesture.StartPos();
   597     event.SetStartPos(aGesture.StartPos());
   783     event->iIsHolding = aGesture.IsHolding();
   598     event.SetIsHolding(aGesture.IsHolding());
   784     event->iSpeed = aGesture.Speed();
   599     event.SetSpeed(aGesture.Speed());
   785     event->iVisual = aGesture.Visual();
       
   786     iEventSender->AddEvent(event);
   600     iEventSender->AddEvent(event);
   787     }
   601     }
   788 
   602 
   789 // ----------------------------------------------------------------------------
   603 // ----------------------------------------------------------------------------
   790 // Return a fresh gesture from the gesture pool (pool of one gesture)
   604 // Return a fresh gesture from the gesture pool (pool of one gesture)