tactilefeedback/tactileclickplugin/src/tactileclickplugin.cpp
changeset 0 d54f32e146dd
child 2 a1cbe1c1d62f
equal deleted inserted replaced
-1:000000000000 0:d54f32e146dd
       
     1 /*
       
     2 * Copyright (c) 2007-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:  The click maker plugin, which
       
    15 *               handles key events at window server process.
       
    16 * Part of:      Tactile Feedback.
       
    17 *
       
    18 */
       
    19 
       
    20 #include <e32std.h>
       
    21 #include <tactilearearegistry.h>
       
    22 #include <tactilefeedbacktrace.h>
       
    23 
       
    24 #include "tactileclickplugin.h"
       
    25 #include "OstTraceDefinitions.h"
       
    26 #ifdef OST_TRACE_COMPILER_IN_USE
       
    27 #include "tactileclickpluginTraces.h"
       
    28 #endif
       
    29 
       
    30 // ======== MEMBER FUNCTIONS ========
       
    31 
       
    32 CTactileClickPlugin::CTactileClickPlugin()
       
    33     {
       
    34     }
       
    35 
       
    36 // ---------------------------------------------------------------------------
       
    37 // 
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 void CTactileClickPlugin::ConstructL()
       
    41     {
       
    42     TRACE( "CTactileClickPlugin::ConstructL - Begin" );
       
    43     
       
    44     // Notice that we intentionally don't connect to feedback server here. 
       
    45     // This is  because some players may try to connect to such servers, 
       
    46     // which don't exist yet when click plugin is loaded.
       
    47     iAreaRegistry = CTactileAreaRegistry::NewL();
       
    48     
       
    49     // We need to store ourselves to thead local storage, so that
       
    50     // Anim Dll plugins can access the feedback functionality
       
    51     Dll::SetTls( this );
       
    52 
       
    53     TRACE( "CTactileClickPlugin::ConstructL - End" );
       
    54     }
       
    55 
       
    56 // ---------------------------------------------------------------------------
       
    57 // We really have to trap ConstructL, because construction of click maker 
       
    58 // plug-in must not fail (otherwise WSERV will panic, resulting in KERN 4 and
       
    59 // re-boot of whole device).
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CTactileClickPlugin* CTactileClickPlugin::NewL()
       
    63     {
       
    64     CTactileClickPlugin* self = new( ELeave ) CTactileClickPlugin;
       
    65     TRAP_IGNORE( self->ConstructL() );
       
    66     return self;
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // 
       
    71 // ---------------------------------------------------------------------------
       
    72 //
       
    73 CTactileClickPlugin::~CTactileClickPlugin()
       
    74     {
       
    75     delete iAreaRegistry;
       
    76     iFeedback.Close();
       
    77     Dll::SetTls( NULL );
       
    78     }
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 // From class CClickMaker.
       
    82 // No implementation needed
       
    83 // ---------------------------------------------------------------------------
       
    84 //
       
    85 void CTactileClickPlugin::KeyEvent( 
       
    86     TEventCode /*aType*/, const TKeyEvent& /*aEvent*/ )
       
    87     {    
       
    88     }
       
    89     
       
    90 // ---------------------------------------------------------------------------
       
    91 // From class CClickMaker.
       
    92 // No implementation needed
       
    93 // ---------------------------------------------------------------------------
       
    94 //
       
    95 void CTactileClickPlugin::PointerEvent( const TPointerEvent& /*aEvent*/ )
       
    96     {
       
    97     }
       
    98 
       
    99 // ---------------------------------------------------------------------------
       
   100 // From class CClickMaker.
       
   101 //
       
   102 // Notice that we really have to check iFeedback handle and iAreaRegistry 
       
   103 // pointer here, because click maker construction must not fail 
       
   104 // (otherwise WSERV will panic) 
       
   105 //
       
   106 // We handle three types of events here:
       
   107 // 
       
   108 // 1. Pointer events coming from window server: For these we do hit testing,
       
   109 //    and use RTactileFeedback to play feedback accordingly.
       
   110 //
       
   111 // 2. Window group open events: These ones we pass to area registry for
       
   112 //    bookkeeping.
       
   113 //
       
   114 // 3. Window group close events: These ones we also pass to area registry, so
       
   115 //    that it can update its bookkeeping.
       
   116 // ---------------------------------------------------------------------------
       
   117 //
       
   118 void CTactileClickPlugin::OtherEvent( TInt aType, TAny* aParam )
       
   119     {
       
   120     // 1. Pointer events 
       
   121     if ( aParam && aType == EEventPointer && iFeedback.Handle() && iAreaRegistry )
       
   122         {
       
   123         TPointerEventData* p = static_cast<TPointerEventData*> ( aParam );
       
   124                  
       
   125         // Extract pointer event from the data given by wserv               
       
   126         TPointerEvent pointerEvent = p->iPointerEvent;
       
   127         
       
   128         // Handle button down and button up events.
       
   129         if ( pointerEvent.iType == TPointerEvent::EButton1Down ||
       
   130              pointerEvent.iType == TPointerEvent::EButton1Up )
       
   131             {
       
   132             OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_PEN_EVENT_1, "e_TACTILE_CLICK_PLUGIN_PEN_EVENT 1");
       
   133             
       
   134             // Adjust position so that it is window -relative
       
   135             pointerEvent.iPosition = ( p->iCurrentPos - p->iWindowOrigin );
       
   136             
       
   137             TInt feedback = 
       
   138                 iAreaRegistry->HitTestPointerEvent( 
       
   139                     pointerEvent, 
       
   140                     p->iWindowGroupId,
       
   141                     p->iClientHandle );  
       
   142                 
       
   143             // There is extra vibra- and audio information in top two bits of
       
   144             // feedback type.    
       
   145             TBool playVibra( EFalse );
       
   146             TBool playAudio( EFalse );
       
   147             
       
   148             if ( pointerEvent.iType == TPointerEvent::EButton1Down )
       
   149                 {
       
   150                 playVibra  = ( ( feedback & KTactileVibraBitDown ) != 0);
       
   151                 playAudio  = ( ( feedback & KTactileAudioBitDown ) != 0);
       
   152                 }
       
   153             else
       
   154                 {
       
   155                 playVibra  = ( ( feedback & KTactileVibraBitUp ) != 0);
       
   156                 playAudio  = ( ( feedback & KTactileAudioBitUp ) != 0);
       
   157                 }
       
   158                         
       
   159             // Clear upper two bytes completely
       
   160             feedback &= 0xffff;
       
   161              
       
   162             if ( feedback != ETouchFeedbackNone )    
       
   163                 {
       
   164                 iFeedback.PlayFeedback( 
       
   165                             static_cast<TTouchLogicalFeedback>( feedback ),
       
   166                             playVibra, 
       
   167                             playAudio );
       
   168                 }
       
   169 
       
   170             OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_PEN_EVENT_0, "e_TACTILE_CLICK_PLUGIN_PEN_EVENT 0");
       
   171             }
       
   172         }
       
   173     // 2. Window group open events    
       
   174     else if ( aType == EEventGroupWindowOpen && iAreaRegistry )
       
   175         {
       
   176         TGroupWindowOpenData* data = static_cast<TGroupWindowOpenData*>( aParam );
       
   177         
       
   178         iAreaRegistry->HandleWindowGroupCreated( 
       
   179             data->iIdentifier,
       
   180             data->iClient );
       
   181         }
       
   182     // 3. Window group close events.    
       
   183     else if ( aType == EEventGroupWindowClose && iAreaRegistry )
       
   184         {
       
   185         TInt identifier = reinterpret_cast<TInt>( aParam ); 
       
   186         
       
   187         iAreaRegistry->HandleWindowGroupClosed( 
       
   188             identifier );
       
   189         }
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------------------------
       
   193 // From class CClickMaker.
       
   194 // This is run when client calls RSoundPlugin::CommandReply -function.
       
   195 //
       
   196 // Handling of individual commands has been moved to dedicated functions,
       
   197 // because data handling requires some effort and relively complex code.
       
   198 // This is due to the mistake in CClickMaker API design, as the data is
       
   199 // not delivered in the same format as it was passed to RSoundPlugin on
       
   200 // client side (client gives data in descriptor, but here the descriptor
       
   201 // needs to be re-built from TAny* pointer, and in addition the lenght
       
   202 // of data needs to be known based on command id).
       
   203 //
       
   204 // Leaving here causes RSoundPlugin::CommandReply to return with an error
       
   205 // code on client side. It is thus important that we leave in case 
       
   206 // command ETactileOpCodeConnect fails, because that way client knows
       
   207 // that feedback won't work and does not attempt to do updates in vain.
       
   208 // ---------------------------------------------------------------------------
       
   209 //
       
   210 TInt CTactileClickPlugin::CommandReplyL( TInt aOpcode, TAny* aArgs )
       
   211     {
       
   212     TRACE2( "CTactileClickPlugin::OtherEvent - Begin, opCode = %d", aOpcode );
       
   213     
       
   214     TInt errCode = KErrNone;
       
   215     
       
   216     switch ( aOpcode )
       
   217         {
       
   218         case ETactileOpCodeConnect:
       
   219             HandleConnectL( aArgs );
       
   220             break;
       
   221         case ETactileOpCodeDisconnect:
       
   222             HandleDisconnect( aArgs );
       
   223             break;
       
   224         case ETactileOpCodeImmediateFeedback:
       
   225             errCode = HandleImmediateFeedback( aArgs );
       
   226             break;
       
   227         default:
       
   228             break;
       
   229         }
       
   230        
       
   231     TRACE( "CTactileClickPlugin::OtherEvent - End" );    
       
   232     
       
   233     return errCode;    
       
   234     };
       
   235 
       
   236 // ---------------------------------------------------------------------------
       
   237 // From class MTactileFeedbackServer
       
   238 //
       
   239 // This function handles instant feedback requests originating inside
       
   240 // window server (i.e. From Anim Dll plugins).
       
   241 // ---------------------------------------------------------------------------
       
   242 //
       
   243 void CTactileClickPlugin::InstantFeedback( TTouchLogicalFeedback aType )
       
   244     {
       
   245     TRACE( "CTactileClickPlugin::InstantFeedback - Begin" );    
       
   246     
       
   247     if ( iFeedback.Handle() )
       
   248         {
       
   249         OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_SERVER_API_1, "e_TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_SERVER_API 1");
       
   250         
       
   251         iFeedback.PlayFeedback( aType, ETrue, ETrue );
       
   252         
       
   253         OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_SERVER_API_0, "e_TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_SERVER_API 0");
       
   254         }
       
   255     }
       
   256 
       
   257 // ---------------------------------------------------------------------------
       
   258 // Handling of connection requests from clients.
       
   259 //
       
   260 // #1 Try to connect to Tactile Feedback server in case it is not yet created,
       
   261 //    and creation has already been attempted (this is an optimization in case
       
   262 //    there is something wrong in the device so that construction cannot 
       
   263 //    succeed).
       
   264 // 
       
   265 // #2 Convert the data and pass connect .command to Area Registry
       
   266 //
       
   267 // #3 In case area registry or server connection does not exist, then leave 
       
   268 //    so that client knows that feedback is not in use.
       
   269 // ---------------------------------------------------------------------------
       
   270 //
       
   271 void CTactileClickPlugin::HandleConnectL( TAny* aArgs )
       
   272     {
       
   273     // #1 Try to connct to RTactileFeedback first (if not yet connected)
       
   274     if ( !iFeedback.Handle() )
       
   275         {
       
   276         // Try to connect to Tactile Feedback server now when first client 
       
   277         // has connected.
       
   278         User::LeaveIfError( iFeedback.Connect() );
       
   279         }
       
   280     
       
   281     // #2
       
   282     if ( aArgs && iAreaRegistry && iFeedback.Handle() )
       
   283         {
       
   284         TInt* tmpInt = reinterpret_cast<TInt*>( aArgs );
       
   285 
       
   286         TInt dataSize = sizeof( TTactileFeedbackConnectData );
       
   287         
       
   288         TPtrC8 tmpConnectData( reinterpret_cast<TUint8*>( tmpInt ), dataSize );
       
   289         
       
   290         TTactileFeedbackConnectData clientData;
       
   291         
       
   292         TPckg<TTactileFeedbackConnectData> dataBuf (clientData);
       
   293         
       
   294         dataBuf.Copy( tmpConnectData );
       
   295         
       
   296         iAreaRegistry->HandleConnectL( clientData );
       
   297         }
       
   298     else
       
   299         {
       
   300         // #3 Fail connection if everything is not in place. This way client
       
   301         // will not waste effort doing updates in vain.
       
   302         User::Leave( KErrGeneral );
       
   303         }
       
   304     }
       
   305         
       
   306 // ---------------------------------------------------------------------------
       
   307 // Handle disconnection requests from clients.
       
   308 //
       
   309 // Here we just convert the data and pass command to Area Registry
       
   310 // ---------------------------------------------------------------------------
       
   311 //
       
   312 void CTactileClickPlugin::HandleDisconnect( TAny* aArgs )
       
   313     {  
       
   314     if ( aArgs && iAreaRegistry )
       
   315         {
       
   316         TInt* tmpInt = reinterpret_cast<TInt*>( aArgs );
       
   317 
       
   318         TInt dataSize = sizeof( TTactileFeedbackDisconnectData );
       
   319         
       
   320         TPtrC8 tmpDisconnectData( reinterpret_cast<TUint8*>( tmpInt ), dataSize );
       
   321         
       
   322         TTactileFeedbackDisconnectData clientData;
       
   323         
       
   324         TPckg<TTactileFeedbackDisconnectData> dataBuf (clientData);
       
   325         
       
   326         dataBuf.Copy( tmpDisconnectData );
       
   327         
       
   328         iAreaRegistry->HandleDisconnect( clientData );
       
   329         }
       
   330     }
       
   331 
       
   332 // ---------------------------------------------------------------------------
       
   333 // Handling of immediate feedback, that originates from client application
       
   334 // (See InstantFeedback function for handling of feedback that originates
       
   335 //  from inside window server)
       
   336 //
       
   337 // We don't need to do any state checks (call in progress) etc. here, 
       
   338 // because Feedback Server will do that anyway. Notice that we rely
       
   339 // on the client API so that it does not send direct feedback in case client
       
   340 // application has disabled feedback from itself.
       
   341 // ---------------------------------------------------------------------------
       
   342 //
       
   343 TInt CTactileClickPlugin::HandleImmediateFeedback( TAny* aArgs )
       
   344     {
       
   345     if ( aArgs && iFeedback.Handle() )
       
   346         {
       
   347         TTactileFeedbackImmediateData* data = 
       
   348             reinterpret_cast<TTactileFeedbackImmediateData*>( aArgs );
       
   349         
       
   350         OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_CLIENT_API_1, "e_TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_CLIENT_API 1");
       
   351         
       
   352        iFeedback.PlayFeedback( data->iFeedbackType, 
       
   353                                       data->iPlayVibra, 
       
   354                                       data->iPlayAudio );  
       
   355 
       
   356         OstTrace0( TACTILE_PERFORMANCE, TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_CLIENT_API_0, "e_TACTILE_CLICK_PLUGIN_INSTANT_FEEDBACK_CLIENT_API 0");
       
   357         }
       
   358     
       
   359     return KErrNone;
       
   360     }
       
   361 
       
   362 // ======== GLOBAL FUNCTIONS ========
       
   363 
       
   364 // ---------------------------------------------------------------------------
       
   365 // Function with this signature needs to be the first exported function
       
   366 // in click maker plugin DLLs.
       
   367 //
       
   368 // Constructs and returns an instance to tactile click maker plugin.
       
   369 // ---------------------------------------------------------------------------
       
   370 //
       
   371 EXPORT_C CClickMaker* CreateClickMakerL()
       
   372     {
       
   373     TRACE( "CreateClickMakerL" );    
       
   374     return CTactileClickPlugin::NewL();
       
   375     }