uifw/AvKon/aknphysics/src/aknphysics.cpp
changeset 0 2f259fa3e83a
child 14 3320e4e6e8bb
child 16 71dd06cfe933
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2009 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 "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:  CAknPhysics
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <aknphysics.h>
       
    20 #include <aknphysicsobserveriface.h>
       
    21 #include <e32debug.h>
       
    22 
       
    23 #include "aknphysicsconstants.h"
       
    24 #include "aknphysicsengine.h"
       
    25 #include "aknphysicsparameterprovider.h"
       
    26 #include "aknphysicsrestrictor.h"
       
    27 #include "aknphysicsconeobserver.h"
       
    28 #include <touchfeedback.h>
       
    29 
       
    30 const TInt KSamePositionStopCount( 3 );
       
    31 
       
    32 _LIT( KNullThreadProcessName, "ekern.exe*" );
       
    33 _LIT( KNullThreadName, "::Null" );
       
    34 
       
    35 #undef AKNHIGHRESPERIODIC_PROFILE
       
    36 
       
    37 /**
       
    38  * Opens a handle to the null thread.
       
    39  */
       
    40 static TBool FindNullThread( RThread& aThread )
       
    41     {
       
    42     TFindProcess fp( KNullThreadProcessName );
       
    43     TFullName kernelName;
       
    44     if ( fp.Next( kernelName ) == KErrNone )
       
    45         {
       
    46         kernelName.Append( KNullThreadName );
       
    47         
       
    48         TFindThread ft( kernelName );
       
    49         TFullName threadName;
       
    50         if ( ft.Next( threadName ) == KErrNone )
       
    51             {
       
    52             if ( aThread.Open( threadName ) != KErrNone )
       
    53                 {
       
    54                 return EFalse;
       
    55                 }
       
    56             }
       
    57         }        
       
    58 
       
    59     return ( aThread.Handle() != 0 );
       
    60     }
       
    61 
       
    62 
       
    63 /**
       
    64  * Periodic timer using CTimer::HighRes.
       
    65  */
       
    66 NONSHARABLE_CLASS( CAknHighResPeriodic ) : public CTimer
       
    67     {
       
    68 public:
       
    69 
       
    70     /**
       
    71      * Creates new timer instance.
       
    72      * 
       
    73      * @param  aPriority    Priority of the timer.
       
    74      * @param  aNullThread  Open thread handle to the null thread,
       
    75      *                      ownership is not transferred.
       
    76      */
       
    77     static CAknHighResPeriodic* NewL( TInt aPriority,
       
    78                                       RThread* aNullThread );
       
    79 
       
    80     /**
       
    81      * Destructor.
       
    82      */
       
    83     ~CAknHighResPeriodic();
       
    84 
       
    85     /**
       
    86      * Starts periodic timer.
       
    87      * 
       
    88      * @param  aDelay      Initial delay.
       
    89      * @param  anInterval  Minimum interval between callback.
       
    90      * @param  aCallBack   Callback to invoke.
       
    91      */
       
    92     void Start( TTimeIntervalMicroSeconds32 aDelay,
       
    93                 TTimeIntervalMicroSeconds32 anInterval,
       
    94                 TCallBack aCallBack );
       
    95 
       
    96     /**
       
    97      * Sets minimum time between end of callback to beginning of next one.
       
    98      *
       
    99      * This is one approach to try to make sure that there is some time for
       
   100      * other processes. If this process can handle callback quickly,
       
   101      * this won't slow down frame rate.
       
   102      * 
       
   103      * @param  aDelay  Minimum time between callbacks.
       
   104      */
       
   105     void SetMinCallBackPeriod( TTimeIntervalMicroSeconds32 aDelay );
       
   106 
       
   107 protected:
       
   108 
       
   109     /**
       
   110      * C++ constructor.
       
   111      * 
       
   112      * @param  aPriority    Priority of the timer.
       
   113      * @param  aNullThread  Open thread handle to the null thread,
       
   114      *                      ownership is not transferred.
       
   115      */
       
   116     CAknHighResPeriodic( TInt aPriority, RThread* aNullThread );
       
   117     
       
   118     /**
       
   119      * Called upon timer completion.
       
   120      */
       
   121     void RunL();
       
   122 
       
   123 private:
       
   124 
       
   125     /**
       
   126      * Prints out the CPU time given to the null thread between this and
       
   127      * the previous call to this method.
       
   128      */
       
   129     void DumpNull();
       
   130     
       
   131 private:
       
   132 
       
   133     /** Timer interval. */
       
   134     TTimeIntervalMicroSeconds32 iInterval;
       
   135     
       
   136     /** Callback of the timer. */
       
   137     TCallBack iCallBack;
       
   138     
       
   139     /** Is the end time valid, i.e. has the timer been completed at least once. */
       
   140     TBool iEndTimeValid;
       
   141     
       
   142     /** Time after the execution of the last timer callback. */
       
   143     TTime iEndTime;
       
   144     
       
   145     /** Minimum interval between callbacks. */
       
   146     TInt64 iMinCallBackPeriod;
       
   147     
       
   148     TBool iWaiting;
       
   149     
       
   150     /** Pointer to the null thread handle, not own. */
       
   151     RThread* iDebugNullThread;
       
   152     
       
   153     /** Null thread CPU time after the last callback. */ 
       
   154     TInt64 iDebugPreviousTime;
       
   155     };
       
   156 
       
   157 
       
   158 // ---------------------------------------------------------------------------
       
   159 // Creates new timer instance
       
   160 // ---------------------------------------------------------------------------
       
   161 //
       
   162 CAknHighResPeriodic* CAknHighResPeriodic::NewL( TInt aPriority,
       
   163                                                 RThread* aNullThread )
       
   164     {
       
   165     CAknHighResPeriodic* self =
       
   166         new (ELeave) CAknHighResPeriodic( aPriority, aNullThread );
       
   167     CleanupStack::PushL( self );
       
   168     self->ConstructL();
       
   169     CleanupStack::Pop( self );
       
   170     return self;
       
   171     }
       
   172 
       
   173 
       
   174 // ---------------------------------------------------------------------------
       
   175 // Destructor
       
   176 // ---------------------------------------------------------------------------
       
   177 //
       
   178 CAknHighResPeriodic::~CAknHighResPeriodic()
       
   179     {
       
   180     }
       
   181 
       
   182 
       
   183 // ---------------------------------------------------------------------------
       
   184 // Starts the periodic timer.
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 void CAknHighResPeriodic::Start( TTimeIntervalMicroSeconds32 aDelay,
       
   188                                  TTimeIntervalMicroSeconds32 anInterval,
       
   189                                  TCallBack aCallBack)
       
   190     {
       
   191     iInterval = anInterval.Int();
       
   192     iCallBack = aCallBack;
       
   193     iEndTimeValid = EFalse;
       
   194     iWaiting = EFalse;
       
   195     HighRes( aDelay );
       
   196     }
       
   197 
       
   198 
       
   199 // ---------------------------------------------------------------------------
       
   200 // Sets minimum time between end of callback to beginning of next one.
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 void CAknHighResPeriodic::SetMinCallBackPeriod(
       
   204     TTimeIntervalMicroSeconds32 aDelay )
       
   205     {
       
   206     if ( aDelay.Int() >= 0 )
       
   207         {
       
   208         iMinCallBackPeriod = aDelay.Int();
       
   209         }
       
   210     else
       
   211         {
       
   212         iMinCallBackPeriod = 0;
       
   213         }
       
   214     }
       
   215 
       
   216 
       
   217 // ---------------------------------------------------------------------------
       
   218 // C++ constructor.
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 CAknHighResPeriodic::CAknHighResPeriodic( TInt aPriority,
       
   222                                           RThread* aNullThread )
       
   223     : CTimer( aPriority ), iDebugNullThread( aNullThread )
       
   224     {
       
   225     CActiveScheduler::Add( this );
       
   226     }
       
   227 
       
   228 
       
   229 // ---------------------------------------------------------------------------
       
   230 // Prints out the CPU time given to the null thread between this and previous
       
   231 // call to this method.
       
   232 // ---------------------------------------------------------------------------
       
   233 //
       
   234 void CAknHighResPeriodic::DumpNull()
       
   235     {
       
   236     TTimeIntervalMicroSeconds time;
       
   237     TInt err = iDebugNullThread->GetCpuTime( time );
       
   238 
       
   239     if ( !err )
       
   240         {
       
   241         if ( !iEndTimeValid )
       
   242             {
       
   243             iDebugPreviousTime = time.Int64();
       
   244             }
       
   245         else
       
   246             {
       
   247             TInt64 delta = time.Int64() - iDebugPreviousTime; 
       
   248             iDebugPreviousTime = time.Int64();
       
   249 #ifdef AKNHIGHRESPERIODIC_PROFILE
       
   250             _LIT( KDMsg1, "[AKNPHYSICS] Null thread CPU time between frames: %d microseconds" );
       
   251             RDebug::Print( KDMsg1, TInt( delta ) );
       
   252 #endif // AKNHIGHRESPERIODIC_PROFILE
       
   253             }
       
   254         }
       
   255     else
       
   256         {
       
   257 #ifdef AKNHIGHRESPERIODIC_PROFILE
       
   258         _LIT( KDMsg2, "[AKNPHYSICS] Error %d in getting null thread CPU time" );
       
   259         RDebug::Print( KDMsg2, err );
       
   260 #endif // AKNHIGHRESPERIODIC_PROFILE
       
   261         }
       
   262     }
       
   263 
       
   264 
       
   265 // ---------------------------------------------------------------------------
       
   266 // Handles timer completion.
       
   267 // ---------------------------------------------------------------------------
       
   268 //
       
   269 void CAknHighResPeriodic::RunL()
       
   270     {
       
   271     if ( iEndTimeValid && !iWaiting ) 
       
   272         {
       
   273         TTime now;
       
   274         now.UniversalTime();
       
   275         
       
   276         TInt64 delta = now.MicroSecondsFrom( iEndTime ).Int64();
       
   277         if ( delta < 0 )
       
   278             {
       
   279             delta = 0;
       
   280             }
       
   281 
       
   282         TInt64 waitTime = iMinCallBackPeriod - delta; 
       
   283         
       
   284         if ( waitTime >= 0 )
       
   285             {
       
   286             // Restrict to some sensible min-max period.
       
   287             if ( waitTime < KAknHighResMinWait )
       
   288                 {
       
   289                 waitTime = KAknHighResMinWait;
       
   290                 }
       
   291 
       
   292             if ( waitTime > KAknHighResMaxWait )
       
   293                 {
       
   294                 waitTime = KAknHighResMaxWait;
       
   295                 }
       
   296 
       
   297             TInt timeToWait( waitTime );
       
   298 
       
   299 #ifdef AKNHIGHRESPERIODIC_PROFILE
       
   300             _LIT( KDmsg, "[AKNPHYSICS] - CAknHighResPeriodic::RunL : waiting for %d microseconds" );
       
   301             RDebug::Print( KDmsg, timeToWait );
       
   302 #endif            
       
   303             iWaiting = ETrue;
       
   304             HighRes( timeToWait );
       
   305             return;
       
   306             }
       
   307         }
       
   308     
       
   309     HighRes( iInterval );
       
   310     iCallBack.CallBack();
       
   311     
       
   312 #ifdef AKNHIGHRESPERIODIC_PROFILE
       
   313 
       
   314     if ( iDebugNullThread && iDebugNullThread->Handle() )
       
   315         {
       
   316         DumpNull();
       
   317         }
       
   318 
       
   319 #endif // AKNHIGHRESPERIODIC_PROFILE
       
   320     
       
   321     iWaiting = EFalse;
       
   322     iEndTime.UniversalTime();
       
   323     iEndTimeValid = ETrue;
       
   324     }
       
   325 
       
   326 
       
   327 
       
   328 // ---------------------------------------------------------------------------
       
   329 // CAknPhysics::NewL()
       
   330 // ---------------------------------------------------------------------------
       
   331 //
       
   332 EXPORT_C CAknPhysics* CAknPhysics::NewL( MAknPhysicsObserver& aObserver,
       
   333                                          CCoeControl* aViewControl )
       
   334     {
       
   335     CAknPhysics* self = new ( ELeave ) CAknPhysics( aObserver );
       
   336     CleanupStack::PushL( self );
       
   337     self->ConstructL( aViewControl );
       
   338     CleanupStack::Pop( self );
       
   339     return self;
       
   340     }
       
   341     
       
   342 // ---------------------------------------------------------------------------
       
   343 // CAknPhysics::~CAknPhysics()
       
   344 // ---------------------------------------------------------------------------
       
   345 //
       
   346 CAknPhysics::~CAknPhysics()
       
   347     {
       
   348     delete iPhysics;
       
   349     delete iEngine;
       
   350     delete iParamProvider;
       
   351     delete iRestrictor;
       
   352     delete iConeObserver;
       
   353 
       
   354     iNullThread.Close();
       
   355     }
       
   356 
       
   357 // ---------------------------------------------------------------------------
       
   358 // CAknPhysics::InitPhysicsL()
       
   359 // ---------------------------------------------------------------------------
       
   360 //
       
   361 EXPORT_C void CAknPhysics::InitPhysicsL( const TSize& aWorldSize, 
       
   362                                          const TSize& aViewSize, 
       
   363                                          TBool aLandscape )
       
   364     {
       
   365     if ( iRestrictor )
       
   366         {
       
   367         // Update always the restrictor parameters.
       
   368         iRestrictor->UpdatePhysicsEnvironment( aWorldSize,
       
   369                                                aViewSize,
       
   370                                                aLandscape );
       
   371         }
       
   372     
       
   373     // Do not initialize if all parameters match with old ones
       
   374     if ( aWorldSize == iWorldSize && aViewSize == iViewSize 
       
   375         && ( ( aLandscape && iLandscape ) || ( !aLandscape && !iLandscape ) ) )
       
   376         {
       
   377         return;    
       
   378         }
       
   379 
       
   380     StopPhysics();
       
   381     iEngine->DeletePhysics();
       
   382 
       
   383     iLandscape = aLandscape;
       
   384 
       
   385     iWorldSize = aWorldSize;
       
   386     iViewSize = aViewSize;
       
   387     if( (iLandscape && aWorldSize.iWidth < aViewSize.iWidth) 
       
   388             || (!iLandscape && aWorldSize.iHeight < aViewSize.iHeight) )
       
   389         {
       
   390         iWorldSize = aViewSize;
       
   391         }
       
   392 
       
   393     TInt64 ih, x, y, w, h, r;
       
   394     if(iLandscape)
       
   395         {
       
   396         ih = iWorldSize.iWidth;
       
   397         x = 1;
       
   398         y = 0;
       
   399         r = iViewSize.iHeight;
       
   400         }
       
   401     else
       
   402         {
       
   403         ih = iWorldSize.iHeight;
       
   404         x = 0;
       
   405         y = 1;
       
   406         r = iViewSize.iWidth;
       
   407         }
       
   408 
       
   409     w = iViewSize.iWidth;
       
   410     h = iViewSize.iHeight;
       
   411     
       
   412     if ( iEngine )
       
   413         {
       
   414         iEngine->CreateWorld( iParamProvider->Gravity() );
       
   415         iEngine->CreatePlanes( ih, x, y, r );
       
   416         iEngine->CreateViewBody( w, h, iParamProvider->ViewMass() );
       
   417         }
       
   418     }
       
   419 
       
   420 
       
   421 // ---------------------------------------------------------------------------
       
   422 // CAknPhysics::StartPhysics
       
   423 // ---------------------------------------------------------------------------
       
   424 //
       
   425 EXPORT_C TBool CAknPhysics::StartPhysics( TPoint& aDrag, 
       
   426                                           const TTime& aStartTime )
       
   427     {
       
   428     // Check that world really exists
       
   429     if ( !iEngine || !iEngine->WorldExists() )
       
   430         {
       
   431         return EFalse;
       
   432         }
       
   433     
       
   434     iSuspended = EFalse;
       
   435 
       
   436     TTime now;
       
   437     now.HomeTime();
       
   438     TInt moveTime( now.MicroSecondsFrom( aStartTime ).Int64() );
       
   439 
       
   440     TBool startPhysics( EFalse );
       
   441     iFlickTimeExceeded = EFalse;
       
   442 
       
   443     // Check if drag direction has changed during drag event
       
   444     // and receive the changed parameters
       
   445     if ( iConeObserver )
       
   446         {
       
   447         iConeObserver->DragChanged( iLandscape, aDrag, moveTime );
       
   448         }
       
   449 
       
   450     // Start physics if drag threshold is exceeded
       
   451     startPhysics = 
       
   452         ( iLandscape && Abs( aDrag.iX ) > DragThreshold() )
       
   453         || ( !iLandscape && Abs( aDrag.iY ) > DragThreshold() );
       
   454         
       
   455     // Check if movetime threshold is exceeded
       
   456     if ( startPhysics && moveTime > KFlickMaxDuration )
       
   457         {
       
   458         iFlickTimeExceeded = ETrue;
       
   459         }
       
   460 
       
   461     // Start physics always if position reveals empty space
       
   462     if ( !startPhysics && iRestrictor )
       
   463         {
       
   464         TPoint viewPosition( iObserver.ViewPosition() );
       
   465         startPhysics = 
       
   466             iRestrictor->PositionRevealsEmptySpace( viewPosition );
       
   467         }
       
   468         
       
   469     // Stop FPS logging here so that panning gets logged correctly. Each
       
   470     // panning always ends with a flick attempt.
       
   471     if ( iParamProvider->FpsLoggingEnabled() )
       
   472         {
       
   473         iEngine->StopFpsLogging();
       
   474         }
       
   475 
       
   476     if ( startPhysics && iEngine )
       
   477         {
       
   478         iEngine->SetViewBodyPosition( iObserver.ViewPosition() );
       
   479         StartPhysics();
       
   480         ApplyDrag( aDrag, moveTime ); 
       
   481         
       
   482         if ( iParamProvider->FpsLoggingEnabled() )
       
   483             {
       
   484             iEngine->StartFpsLogging();
       
   485             }
       
   486             
       
   487         return ETrue;
       
   488         }
       
   489     return EFalse;
       
   490     }
       
   491 
       
   492 
       
   493 // ---------------------------------------------------------------------------
       
   494 // CAknPhysics::StopPhysics()
       
   495 // ---------------------------------------------------------------------------
       
   496 //
       
   497 EXPORT_C void CAknPhysics::StopPhysics()
       
   498     {
       
   499     // Check that world really exists
       
   500     if ( !iEngine || !iEngine->WorldExists() )
       
   501         {
       
   502         return;
       
   503         }
       
   504     
       
   505     iSuspended = EFalse;
       
   506 
       
   507     iSamePositionCounter = 0;
       
   508     
       
   509     if ( iPhysics && iPhysics->IsActive() )
       
   510         {
       
   511         if ( iParamProvider->FpsLoggingEnabled() )
       
   512             {
       
   513             iEngine->StopFpsLogging();
       
   514             }
       
   515 
       
   516         CancelPhysicsTimer();
       
   517     
       
   518         if ( iEngine )
       
   519             {
       
   520             iEngine->ResetViewBodyForceAndVelocity();
       
   521             }
       
   522         iObserver.PhysicEmulationEnded();
       
   523         }
       
   524     else
       
   525         {
       
   526         UpdateActionState();
       
   527         }
       
   528     }
       
   529 
       
   530 
       
   531 // ---------------------------------------------------------------------------
       
   532 // CAknPhysics::OngoingPhysicsAction
       
   533 // ---------------------------------------------------------------------------
       
   534 //
       
   535 EXPORT_C TInt CAknPhysics::OngoingPhysicsAction() const
       
   536     {
       
   537     return iOngoingAction;
       
   538     }
       
   539 
       
   540 
       
   541 // ---------------------------------------------------------------------------
       
   542 // CAknPhysics::RegisterPanningPosition
       
   543 // ---------------------------------------------------------------------------
       
   544 //
       
   545 EXPORT_C void CAknPhysics::RegisterPanningPosition( const TPoint& aDelta )
       
   546     {
       
   547     TTimeIntervalMicroSeconds time;
       
   548     TInt err( KErrNone );
       
   549     if ( iNullThread.Handle() )
       
   550         {
       
   551         err = iNullThread.GetCpuTime( time );
       
   552         }
       
   553     else
       
   554         {
       
   555         err = KErrBadHandle;
       
   556         }
       
   557     
       
   558     TInt64 nullDelta = !err ? time.Int64() - iNullThreadTime : KMaxTInt64;
       
   559     
       
   560     TTime now;
       
   561     now.UniversalTime();
       
   562     
       
   563     TInt64 delta = Max( 0, now.MicroSecondsFrom( iTimeOfLastDraw ).Int64() );
       
   564     
       
   565 #ifdef AKNHIGHRESPERIODIC_PROFILE
       
   566 
       
   567     _LIT( KDMsg1, "[AKNPHYSICS] - RegisterPanningPosition : Null thread CPU time between frames: %d microseconds" );
       
   568     _LIT( KDMsg2, "[AKNPHYSICS] - RegisterPanningPosition : Last draw %d microseconds ago");
       
   569     RDebug::Print( KDMsg1, TInt( nullDelta ) );
       
   570     RDebug::Print( KDMsg2, TInt( delta ) );
       
   571     
       
   572     if ( err )
       
   573         {
       
   574         _LIT( KDMsg3, "[AKNPHYSICS] Error %d in getting null thread CPU time" );
       
   575         RDebug::Print( KDMsg3, err );
       
   576         }
       
   577     
       
   578 #endif // AKNHIGHRESPERIODIC_PROFILE
       
   579     
       
   580     TBool drawNow = EFalse;
       
   581     if ( nullDelta > FrameDelay() * 1000 ||       // There has been enough idle time.
       
   582          delta > MinFrameInterval() * 1000 ||     // Enough time since last draw.
       
   583          iTimeOfLastDraw.Int64() == Int64( 0 ) || // First draw.
       
   584          nullDelta < 0 )                          // Null thread CPU time not valid.
       
   585         {
       
   586         drawNow = ETrue;
       
   587         }
       
   588 
       
   589     iPanningDrawOmitted = !drawNow;
       
   590     
       
   591     TPoint position( iObserver.ViewPosition() );
       
   592     position += aDelta;
       
   593 
       
   594     if ( iRestrictor && iRestrictor->AllowedViewPosition( position ) )
       
   595         {
       
   596         if ( OngoingPhysicsAction() == EAknPhysicsActionNone )
       
   597             {
       
   598             iOngoingAction = EAknPhysicsActionDragging;
       
   599             
       
   600             if ( iParamProvider->FpsLoggingEnabled() )
       
   601                 {
       
   602                 iEngine->StartFpsLogging();
       
   603                 }
       
   604             }
       
   605         
       
   606         NotifyViewPositionChanged( position, drawNow );
       
   607         
       
   608         if ( drawNow )
       
   609             {
       
   610             // Update the CPU time that the null thread has gotten.
       
   611             iNullThreadTime = time.Int64();
       
   612             }
       
   613         }
       
   614     }
       
   615 
       
   616 
       
   617 // ---------------------------------------------------------------------------
       
   618 // CAknPhysics::SetFriction()
       
   619 // ---------------------------------------------------------------------------
       
   620 //
       
   621 EXPORT_C void CAknPhysics::SetFriction( TReal aFriction )
       
   622     {
       
   623     if ( iEngine )
       
   624         {
       
   625         iEngine->SetFriction( aFriction );
       
   626         }
       
   627     }
       
   628 
       
   629 
       
   630 // ---------------------------------------------------------------------------
       
   631 // CAknPhysics::ResetFriction()
       
   632 // ---------------------------------------------------------------------------
       
   633 //
       
   634 EXPORT_C void CAknPhysics::ResetFriction()
       
   635     {
       
   636     if ( iEngine )
       
   637         {
       
   638         iEngine->ResetFriction();
       
   639         }
       
   640     }
       
   641 
       
   642 
       
   643 // ---------------------------------------------------------------------------
       
   644 // CAknPhysics::HighlightTimeOut
       
   645 // ---------------------------------------------------------------------------
       
   646 //
       
   647 EXPORT_C TInt CAknPhysics::HighlightTimeout() const
       
   648     {
       
   649     if ( iParamProvider )
       
   650         {
       
   651         return iParamProvider->HighlightTimeout();
       
   652         }
       
   653     return 0;
       
   654     }
       
   655 
       
   656 
       
   657 // ---------------------------------------------------------------------------
       
   658 // CAknPhysics::DragThreshold
       
   659 // ---------------------------------------------------------------------------
       
   660 //
       
   661 EXPORT_C TInt CAknPhysics::DragThreshold() const
       
   662     {
       
   663     if ( iParamProvider )
       
   664         {
       
   665         return iParamProvider->DragThreshold();
       
   666         }
       
   667     return 0;
       
   668     }
       
   669 
       
   670 
       
   671 // ---------------------------------------------------------------------------
       
   672 // CAknPhysics::FeatureEnabled
       
   673 // ---------------------------------------------------------------------------
       
   674 //
       
   675 EXPORT_C TBool CAknPhysics::FeatureEnabled()
       
   676     {
       
   677     return CAknPhysicsParameterProvider::FeatureEnabled();
       
   678     }
       
   679 
       
   680 
       
   681 // ---------------------------------------------------------------------------
       
   682 // CAknPhysics::EventHandlingAllowed
       
   683 // ---------------------------------------------------------------------------
       
   684 //
       
   685 EXPORT_C TBool CAknPhysics::EventHandlingAllowed() const
       
   686     {
       
   687     if ( iConeObserver )
       
   688         {
       
   689         return iConeObserver->EventHandlingAllowed();
       
   690         }
       
   691     return ETrue;
       
   692     }
       
   693 
       
   694 
       
   695 // ---------------------------------------------------------------------------
       
   696 // CAknPhysics::UpdateViewWindowControl
       
   697 // ---------------------------------------------------------------------------
       
   698 //
       
   699 EXPORT_C void CAknPhysics::UpdateViewWindowControl( CCoeControl* aControl )
       
   700     {
       
   701     if ( iConeObserver )
       
   702         {
       
   703         iConeObserver->UpdateViewWindowControl( aControl );
       
   704         }
       
   705     }
       
   706 
       
   707 
       
   708 // ---------------------------------------------------------------------------
       
   709 // CAknPhysics::SuspendPhysics
       
   710 // ---------------------------------------------------------------------------
       
   711 //
       
   712 EXPORT_C void CAknPhysics::SuspendPhysics()
       
   713     {
       
   714     // Check that world really exists
       
   715     if ( !iEngine || !iEngine->WorldExists() )
       
   716         {
       
   717         return;
       
   718         }
       
   719     
       
   720     if ( iSuspended )
       
   721         {
       
   722         // Already suspended
       
   723         return;
       
   724         }
       
   725     iSuspended = ETrue;
       
   726     
       
   727     iSamePositionCounter = 0;
       
   728     if ( iPhysics && iPhysics->IsActive() )
       
   729         {
       
   730         if ( iParamProvider->FpsLoggingEnabled() )
       
   731             {
       
   732             iEngine->StopFpsLogging();
       
   733             }
       
   734         CancelPhysicsTimer();
       
   735         }
       
   736     else
       
   737         {
       
   738         UpdateActionState();
       
   739         }
       
   740     }
       
   741 
       
   742 
       
   743 // ---------------------------------------------------------------------------
       
   744 // CAknPhysics::ResumePhysics
       
   745 // ---------------------------------------------------------------------------
       
   746 //
       
   747 EXPORT_C void CAknPhysics::ResumePhysics()
       
   748     {
       
   749     if ( !iEngine || !iEngine->WorldExists() )
       
   750         {
       
   751         return;
       
   752         }
       
   753     
       
   754     if ( !iSuspended )
       
   755         {
       
   756         // Not suspended
       
   757         return;
       
   758         }
       
   759     iSuspended = EFalse;
       
   760     
       
   761     if ( iParamProvider->FpsLoggingEnabled() )
       
   762         {
       
   763         iEngine->StopFpsLogging();
       
   764         }
       
   765 
       
   766     iEngine->SetViewBodyPosition( iObserver.ViewPosition() );
       
   767     StartPhysics();         
       
   768             
       
   769     if ( iParamProvider->FpsLoggingEnabled() )
       
   770         {
       
   771         iEngine->StartFpsLogging();
       
   772         }
       
   773     }
       
   774 
       
   775 
       
   776 // ---------------------------------------------------------------------------
       
   777 // CAknPhysics::UpdateViewPosition
       
   778 // ---------------------------------------------------------------------------
       
   779 //
       
   780 void CAknPhysics::UpdateViewPosition()
       
   781     {
       
   782     if ( iOngoingAction == CAknPhysics::EAknPhysicsActionNone
       
   783          || iOngoingAction == CAknPhysics::EAknPhysicsActionDragging )
       
   784         {
       
   785         TPoint viewPosition( iObserver.ViewPosition() );
       
   786         if ( iRestrictor 
       
   787             && iRestrictor->PositionRevealsEmptySpace( viewPosition ) )
       
   788             {
       
   789             NotifyViewPositionChanged( viewPosition );            
       
   790             }
       
   791         }
       
   792     }
       
   793 
       
   794 
       
   795 // ---------------------------------------------------------------------------
       
   796 // CAknPhysics::Landscape
       
   797 // ---------------------------------------------------------------------------
       
   798 //
       
   799 const TBool& CAknPhysics::Landscape()
       
   800     {
       
   801     return iLandscape;
       
   802     }
       
   803 
       
   804 
       
   805 // ---------------------------------------------------------------------------
       
   806 // CAknPhysics::ViewSize
       
   807 // ---------------------------------------------------------------------------
       
   808 //
       
   809 const TSize& CAknPhysics::ViewSize()
       
   810     {
       
   811     return iViewSize;
       
   812     }
       
   813 
       
   814 
       
   815 // ---------------------------------------------------------------------------
       
   816 // CAknPhysics::WorldSize
       
   817 // ---------------------------------------------------------------------------
       
   818 //
       
   819 const TSize& CAknPhysics::WorldSize()
       
   820     {
       
   821     return iWorldSize;
       
   822     }
       
   823 
       
   824 
       
   825 // ---------------------------------------------------------------------------
       
   826 // CAknPhysics::SurfaceErp
       
   827 // ---------------------------------------------------------------------------
       
   828 //
       
   829 TInt CAknPhysics::SurfaceErp() const
       
   830     {
       
   831     if ( iParamProvider )
       
   832         {
       
   833         return iParamProvider->SurfaceErp();
       
   834         }
       
   835     return 0;
       
   836     }
       
   837 
       
   838 
       
   839 // ---------------------------------------------------------------------------
       
   840 // CAknPhysics::SurfaceCfm
       
   841 // ---------------------------------------------------------------------------
       
   842 //
       
   843 TInt CAknPhysics::SurfaceCfm() const
       
   844     {
       
   845     if ( iParamProvider )
       
   846         {
       
   847         return iParamProvider->SurfaceCfm();
       
   848         }
       
   849     return 0;
       
   850     }
       
   851 
       
   852 // ---------------------------------------------------------------------------
       
   853 // CAknPhysics::IsPanningDrawIgnored
       
   854 // ---------------------------------------------------------------------------
       
   855 //
       
   856 TBool CAknPhysics::IsPanningDrawOmitted() const
       
   857     {
       
   858     return iPanningDrawOmitted;
       
   859     }
       
   860 
       
   861 
       
   862 
       
   863 // ---------------------------------------------------------------------------
       
   864 // CAknPhysics::FrameDelay
       
   865 // ---------------------------------------------------------------------------
       
   866 //
       
   867 TInt CAknPhysics::FrameDelay() const
       
   868     {
       
   869     if ( iParamProvider )
       
   870         {
       
   871         return iParamProvider->FrameDelay();
       
   872         }
       
   873 
       
   874     return KPhysicsMinTime / 1000;
       
   875     }
       
   876 
       
   877 
       
   878 // ---------------------------------------------------------------------------
       
   879 // CAknPhysics::MinFrameInterval
       
   880 // ---------------------------------------------------------------------------
       
   881 //
       
   882 TInt CAknPhysics::MinFrameInterval() const
       
   883     {
       
   884     if ( iParamProvider )
       
   885         {
       
   886         return iParamProvider->MinFrameInterval();
       
   887         }
       
   888 
       
   889     return KPhysicsTime / 1000;
       
   890     }
       
   891 
       
   892 
       
   893 // ---------------------------------------------------------------------------
       
   894 // CAknPhysics::DrawViewInCurrentPosition
       
   895 // ---------------------------------------------------------------------------
       
   896 //
       
   897 void CAknPhysics::DrawViewInCurrentPosition()
       
   898     {
       
   899     NotifyViewPositionChanged( iObserver.ViewPosition(), ETrue );
       
   900     }
       
   901 
       
   902 // --------------------------------------------------------------------------
       
   903 // CAknPhysics::SetBounceTactileFeedback
       
   904 // --------------------------------------------------------------------------
       
   905 //
       
   906 void CAknPhysics::SetBounceTactileFeedback( TBool aBounceTactileFeedback )
       
   907     {
       
   908     iBounceTactileFeedback = aBounceTactileFeedback;
       
   909     }
       
   910 
       
   911 // ---------------------------------------------------------------------------
       
   912 // CAknPhysics::CAknPhysics
       
   913 // ---------------------------------------------------------------------------
       
   914 //
       
   915 CAknPhysics::CAknPhysics( MAknPhysicsObserver& aObserver )
       
   916     : iObserver( aObserver ),
       
   917     iOngoingAction( EAknPhysicsActionNone ),
       
   918     iParamProvider( NULL ),
       
   919     iRestrictor( NULL ),
       
   920     iConeObserver( NULL ),
       
   921     iEngine( NULL ),
       
   922     iNullThreadTime( 0 ),
       
   923     iTimeOfLastDraw( 0 ), 
       
   924     iBounceTactileFeedback( ETrue ),
       
   925     iPanningDrawOmitted( EFalse )
       
   926     {
       
   927     }
       
   928 
       
   929 
       
   930 // ---------------------------------------------------------------------------
       
   931 // CAknPhysics::ConstructL()
       
   932 // ---------------------------------------------------------------------------
       
   933 //
       
   934 void CAknPhysics::ConstructL( CCoeControl* aViewControl )
       
   935     {
       
   936     // Open the handle to the null thread.
       
   937     TBool nullThreadOpen = FindNullThread( iNullThread );
       
   938     
       
   939     // Create Physics timer to step physics emulation
       
   940     iPhysics = CAknHighResPeriodic::NewL(
       
   941         CActive::EPriorityStandard, nullThreadOpen ? &iNullThread : NULL );
       
   942     iPhysics->SetMinCallBackPeriod( FrameDelay() * 1000 );
       
   943     
       
   944     iEngine = CAknPhysicsEngine::NewL( this );
       
   945     iParamProvider = CAknPhysicsParameterProvider::NewL();
       
   946     iRestrictor = CAknPhysicsRestrictor::NewL( iParamProvider );
       
   947     iConeObserver = CAknPhysicsConeObserver::NewL( this, iRestrictor );
       
   948     iConeObserver->SetViewWindowControl( aViewControl );
       
   949     iFeedback = MTouchFeedback::Instance();
       
   950     }
       
   951 
       
   952 
       
   953 // ---------------------------------------------------------------------------
       
   954 // CAknPhysics::StartPhysics()
       
   955 // ---------------------------------------------------------------------------
       
   956 //
       
   957 void CAknPhysics::StartPhysics()
       
   958     {
       
   959     // Check that world really exists
       
   960     if ( !iEngine || !iEngine->WorldExists() )
       
   961         {
       
   962         return;
       
   963         }
       
   964 
       
   965     iEngine->ResetCollisionState();
       
   966     iEngine->EnableViewBody();
       
   967     CancelPhysicsTimer();
       
   968     if ( iPhysics && !iPhysics->IsActive() )
       
   969         {
       
   970         iPhysics->Start(
       
   971                 0, KPhysicsTime, TCallBack( CAknPhysics::Simulate, this ) );
       
   972 		UpdateActionState();
       
   973         }
       
   974     }
       
   975 
       
   976 
       
   977 // ---------------------------------------------------------------------------
       
   978 // CAknPhysics::ApplyDrag()
       
   979 // ---------------------------------------------------------------------------
       
   980 //
       
   981 void CAknPhysics::ApplyDrag( TPoint aDrag, TInt aMoveTime )
       
   982     {
       
   983     // Check that world really exists
       
   984     if ( !iEngine || !iEngine->WorldExists() )
       
   985         {
       
   986         return;
       
   987         }
       
   988     
       
   989     if ( iRestrictor )
       
   990         {
       
   991         iRestrictor->AdjustDragPoint( aDrag );
       
   992         }
       
   993 
       
   994     iEngine->ResetCollisionState();
       
   995 
       
   996     if(iLandscape)
       
   997         {
       
   998         if(aDrag.iY > iViewSize.iHeight/2 || aDrag.iY < -iViewSize.iHeight/2)
       
   999             aDrag.iX = 0;
       
  1000         else
       
  1001             aDrag.iY = 0;
       
  1002         }
       
  1003     else
       
  1004         {
       
  1005         if(aDrag.iX > iViewSize.iWidth/2 || aDrag.iX < -iViewSize.iWidth/2)
       
  1006             aDrag.iY = 0;
       
  1007         else
       
  1008             aDrag.iX = 0;
       
  1009         }
       
  1010 
       
  1011     if( aMoveTime < KSwipeDuration )
       
  1012         {
       
  1013         iEngine->ApplyDragForce( aDrag, aMoveTime );
       
  1014         }
       
  1015     }
       
  1016 
       
  1017 
       
  1018 // ---------------------------------------------------------------------------
       
  1019 // CAknPhysics::Simulate()
       
  1020 // ---------------------------------------------------------------------------
       
  1021 //
       
  1022 TInt CAknPhysics::Simulate(TAny* aSelf)
       
  1023     {
       
  1024     CAknPhysics* self = (CAknPhysics*) aSelf;
       
  1025     self->DoSimulation();
       
  1026     return KErrNone;
       
  1027     }
       
  1028 
       
  1029 
       
  1030 // ---------------------------------------------------------------------------
       
  1031 // CAknPhysics::DoSimulation()
       
  1032 // ---------------------------------------------------------------------------
       
  1033 //
       
  1034 void CAknPhysics::DoSimulation()
       
  1035     {
       
  1036     if ( iFlickTimeExceeded && iOngoingAction != EAknPhysicsActionBouncing  )
       
  1037         {
       
  1038         iFlickTimeExceeded = EFalse;
       
  1039         StopPhysics();
       
  1040         return;
       
  1041         }
       
  1042 
       
  1043     TPoint previousViewPosition;
       
  1044     TPoint currentViewPosition;
       
  1045 
       
  1046     // get position before step
       
  1047     iEngine->GetViewBodyPosition( previousViewPosition );
       
  1048     
       
  1049     CAknPhysicsEngine::TAknPhysicsCollision prevState = iEngine->CollisionState();
       
  1050 
       
  1051     iEngine->TakePhysicsStep();
       
  1052 
       
  1053     // get position after step
       
  1054     iEngine->GetViewBodyPosition( currentViewPosition );
       
  1055     
       
  1056     // Signal physics stop only after a possible view position change has been 
       
  1057     // communicated.
       
  1058     TBool stopPhysics = EFalse;
       
  1059     
       
  1060     // if iViewBody gets auto disabled, it's safe to stop physics emulation 
       
  1061     if( !iEngine->IsViewBodyEnabled() )
       
  1062         {
       
  1063         stopPhysics = ETrue;
       
  1064         }
       
  1065     else if ( prevState != CAknPhysicsEngine::EAknPhysicsNoCollision )
       
  1066         {
       
  1067 
       
  1068         TBool collisionChanged( 
       
  1069             iEngine->CollisionState() != CAknPhysicsEngine::EAknPhysicsNoCollision 
       
  1070             && iEngine->CollisionState() != prevState );
       
  1071         TBool topCollision( prevState == CAknPhysicsEngine::EAknPhysicsTopCollision );
       
  1072         TBool previousOut( EFalse );
       
  1073         TBool currentOut( EFalse );
       
  1074 
       
  1075         // Check if positions are out of boundaries
       
  1076         if ( iRestrictor )
       
  1077             {
       
  1078             previousOut = iRestrictor->PositionIsOutOfBoundaries( 
       
  1079                 previousViewPosition, topCollision );
       
  1080             currentOut = iRestrictor->PositionIsOutOfBoundaries( 
       
  1081                 currentViewPosition, topCollision );
       
  1082             }
       
  1083 
       
  1084         // Stop bounce if
       
  1085         // 1) Collision has changed from top to bottom or bottom to top
       
  1086         // 2) Current view position is out of boundaries (and previous was not)
       
  1087         // -> prevent view flicking when bounce ends
       
  1088         // 3) Collision type has changed to no collision and both of the view
       
  1089         // positions are inside view boundaries.
       
  1090         if ( collisionChanged 
       
  1091             || currentOut && !previousOut
       
  1092             || !currentOut && !previousOut 
       
  1093             && iEngine->CollisionState() == CAknPhysicsEngine::EAknPhysicsNoCollision )
       
  1094             {
       
  1095             if ( topCollision || collisionChanged )
       
  1096                 {
       
  1097                 iRestrictor->PositionToViewTop( currentViewPosition );
       
  1098                 }
       
  1099             else
       
  1100                 {
       
  1101                 iRestrictor->PositionToViewBottom( currentViewPosition );
       
  1102                 }
       
  1103             stopPhysics = ETrue;
       
  1104             iEngine->ResetCollisionState();
       
  1105             // boundary effect                       
       
  1106             if ( iBounceTactileFeedback && iFeedback )
       
  1107                 {
       
  1108                 iFeedback->InstantFeedback( NULL,
       
  1109                                             ETouchFeedbackBoundaryList,
       
  1110                                             ETouchFeedbackVibra,
       
  1111                                             TPointerEvent() );
       
  1112                 }
       
  1113             }
       
  1114 
       
  1115         // Previous view position and current view position are out of view
       
  1116         // boundaries -> bounce has changed to flick
       
  1117         else if ( currentOut && previousOut )
       
  1118             {
       
  1119             iEngine->ResetCollisionState();
       
  1120             }
       
  1121         }
       
  1122 
       
  1123     UpdateActionState();
       
  1124 
       
  1125     if ( currentViewPosition == previousViewPosition )
       
  1126         {
       
  1127         iSamePositionCounter++;
       
  1128         // Never stop physics while bouncing even though
       
  1129         // same position count has been exceeded
       
  1130         if ( iOngoingAction != EAknPhysicsActionBouncing 
       
  1131             && iSamePositionCounter >= KSamePositionStopCount )
       
  1132             {
       
  1133             stopPhysics = ETrue;
       
  1134             }
       
  1135         }
       
  1136 
       
  1137     NotifyViewPositionChanged( currentViewPosition );
       
  1138        
       
  1139     if ( stopPhysics )
       
  1140         {
       
  1141         StopPhysics();
       
  1142         }
       
  1143     }
       
  1144 
       
  1145 
       
  1146 // ---------------------------------------------------------------------------
       
  1147 // CAknPhysics::CancelPhysicsTimer()
       
  1148 // ---------------------------------------------------------------------------
       
  1149 //
       
  1150 void CAknPhysics::CancelPhysicsTimer()
       
  1151     {
       
  1152     if ( iPhysics )
       
  1153         {
       
  1154         iPhysics->Cancel();
       
  1155         UpdateActionState();
       
  1156         }
       
  1157     }
       
  1158 
       
  1159 
       
  1160 // ---------------------------------------------------------------------------
       
  1161 // CAknPhysics::UpdateActionState()
       
  1162 // ---------------------------------------------------------------------------
       
  1163 //
       
  1164 void CAknPhysics::UpdateActionState()
       
  1165     {
       
  1166     if ( iPhysics && iPhysics->IsActive() )
       
  1167         {
       
  1168         // If we are colliding or physics timer is active and view is about
       
  1169         // to bounce -> action to bouncing
       
  1170         if ( iEngine->CollisionState() != CAknPhysicsEngine::EAknPhysicsNoCollision
       
  1171             || ( iOngoingAction == EAknPhysicsActionNone && ViewAboutToBounce() ) )
       
  1172             {
       
  1173             iOngoingAction = EAknPhysicsActionBouncing;
       
  1174             }
       
  1175         // Otherwise we are flicking
       
  1176         else
       
  1177             {
       
  1178             iOngoingAction = EAknPhysicsActionFlicking;
       
  1179             }
       
  1180         }
       
  1181     else
       
  1182         {
       
  1183         iOngoingAction = EAknPhysicsActionNone;
       
  1184         }
       
  1185 
       
  1186     if ( iConeObserver )
       
  1187         {
       
  1188         iConeObserver->PhysicsStateChanged();
       
  1189         }
       
  1190     }
       
  1191 
       
  1192 
       
  1193 // ---------------------------------------------------------------------------
       
  1194 // CAknPhysics::ViewAboutToBounce()
       
  1195 // ---------------------------------------------------------------------------
       
  1196 //
       
  1197 TBool CAknPhysics::ViewAboutToBounce()
       
  1198     {
       
  1199     TPoint viewPosition( iObserver.ViewPosition() );
       
  1200     if ( iRestrictor && iRestrictor->PositionRevealsEmptySpace( viewPosition ) )
       
  1201         {
       
  1202         return ETrue;
       
  1203         }
       
  1204     return EFalse;
       
  1205     }
       
  1206 
       
  1207 
       
  1208 // ---------------------------------------------------------------------------
       
  1209 // CAknPhysics::NotifyViewPositionChanged
       
  1210 // ---------------------------------------------------------------------------
       
  1211 //
       
  1212 void CAknPhysics::NotifyViewPositionChanged( const TPoint& aPosition,
       
  1213                                              TBool aDrawNow )
       
  1214     {
       
  1215     iObserver.ViewPositionChanged( aPosition, aDrawNow, 0 );
       
  1216     
       
  1217     if ( aDrawNow )
       
  1218         {
       
  1219         // Update the time of the last draw.
       
  1220         iTimeOfLastDraw.UniversalTime();
       
  1221         }
       
  1222     }
       
  1223 
       
  1224 // End of File