htiui/HtiServicePlugins/HtiKeyEventServicePlugin/src/PointerEventHandler.cpp
changeset 0 d6fe6244b863
child 3 2703485a934c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiKeyEventServicePlugin/src/PointerEventHandler.cpp	Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,542 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Functional implementation of pointer event service
+*
+*/
+
+
+// INCLUDE FILES
+#include "HtiKeyEventServiceplugin.h"
+#include "PointerEventHandler.h"
+
+#include <HtiDispatcherInterface.h>
+#include <HTILogging.h>
+
+
+// CONSTANTS
+_LIT8( KErrorMissingCommand, "Command was not given - message was empty" );
+_LIT8( KErrorServiceNotReady, "Service is busy - possibly executing long running pointer events" );
+_LIT8( KErrorInvalidParameters, "Command parameters not valid" );
+_LIT8( KErrorUnrecognizedCommand, "Unrecognized command" );
+_LIT8( KErrorInternalFailure, "Internal pointer command failure" );
+
+const TInt KTapCmdLength = 10;
+const TInt KDragMultiCmdMinLength = 14;
+const TInt KSinglePointerCmdLength = 4;
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::NewL()
+// ----------------------------------------------------------------------------
+CPointerEventHandler* CPointerEventHandler::NewL()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::NewL" );
+    CPointerEventHandler* self = new (ELeave) CPointerEventHandler();
+    CleanupStack::PushL ( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::Done" );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::CPointerEventHandler()
+// ----------------------------------------------------------------------------
+CPointerEventHandler::CPointerEventHandler()
+    : CActive( CActive::EPriorityStandard ), iReady( ETrue ), iCommand( 0 ),
+      iState( EPointerUp )
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::~CPointerEventHandler()
+// ----------------------------------------------------------------------------
+CPointerEventHandler::~CPointerEventHandler()
+    {
+    HTI_LOG_TEXT( "CPointerEventHandler destroy" );
+    Cancel();
+    iTimer.Close();
+    iWsSession.Close();
+    if ( iCoords )
+        {
+        iCoords->Close();
+        }
+    delete iCoords;
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::ConstructL()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::ConstructL()
+    {
+    HTI_LOG_TEXT( "CPointerEventHandler::ConstructL" );
+    User::LeaveIfError( iWsSession.Connect() );
+    User::LeaveIfError( iTimer.CreateLocal() );
+    CActiveScheduler::Add( this );
+    }
+
+// ----------------------------------------------------------------------------
+// void CPointerEventHandler::SetDispatcher()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::SetDispatcher( MHtiDispatcher* aDispatcher )
+    {
+    iDispatcher = aDispatcher;
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::RunL()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::RunL()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::RunL" );
+
+    if ( iCommand == ETapScreen )
+        {
+        ChangePointerStateL();
+        }
+
+    else if ( iCommand == ETapAndDrag && iState == EPointerDown )
+        {
+        PointerMove();
+        PointerUp();
+        SendOkMsgL();
+        iReady = ETrue;
+        }
+
+    else if ( iCommand == ETapAndDragMultipoint )
+        {
+        if ( iState == EPointerUp )  // Starting a new line
+            {
+            PointerDown();
+            iTapCount--;
+            iTimer.After( iStatus, iEventDelay );
+            SetActive();
+            }
+        else
+            {
+            MoveToNextPointL(); // Continuing current line
+            }
+        }
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::RunL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::RunError()
+// ----------------------------------------------------------------------------
+TInt CPointerEventHandler::RunError( TInt aError )
+    {
+    HTI_LOG_FORMAT( "CPointerEventHandler::RunError %d", aError );
+
+    TInt dispatchResult = KErrNone;
+    TRAP( dispatchResult, SendErrorMessageL( aError, KErrorInternalFailure ) );
+    if ( dispatchResult != KErrNone )
+        {
+        HTI_LOG_FORMAT( "CPointerEventHandler::RunError: Failed to send error report to framework: %d.", dispatchResult );
+        }
+    iReady = ETrue;
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::DoCancel()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::DoCancel()
+    {
+    iTimer.Cancel();
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::ProcessMessageL()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::ProcessMessageL( const TDesC8& aMessage,
+    THtiMessagePriority /*aPriority*/ )
+    {
+    HTI_LOG_FUNC_IN("CPointerEventHandler::ProcessMessageL");
+    HTI_LOG_FORMAT("Msg len: %d.", aMessage.Length());
+
+    if ( !iReady )
+        {
+        SendErrorMessageL( ENotReadyCommand, KErrorServiceNotReady );
+        return;
+        }
+    if ( aMessage.Length() == 0 )
+        {
+        SendErrorMessageL( EMissingCommand, KErrorMissingCommand );
+        return;
+        }
+
+    User::ResetInactivityTime();
+    iCommand = aMessage.Ptr()[0];
+    switch ( iCommand )
+        {
+        case ETapScreen:
+            HandleTapScreenL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+        case ETapAndDrag:
+            HandleTapAndDragL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+        case ETapAndDragMultipoint:
+            HandleTapAndDragMultipointL(
+                aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+        case EPressPointerDown:
+        case ELiftPointerUp:
+            HandlePointerDownOrUpL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+        default:
+            SendErrorMessageL( EUnrecognizedCommand,
+                KErrorUnrecognizedCommand );
+            break;
+        }
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::ProcessMessageL: Done" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::HandleTapScreenL()
+// Handles single or multiple taps to one point.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::HandleTapScreenL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::HandleTapScreenL" );
+
+    if ( aData.Length() != KTapCmdLength )
+        {
+        SendErrorMessageL( EInvalidParameters, KErrorInvalidParameters );
+        return;
+        }
+
+    // Parse the parameters - correct length is already verified
+    TInt offset = 0;
+    iX = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "X coord = %d", iX );
+    iY = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "Y coord = %d", iY );
+    iEventDelay = ( aData[offset] + ( aData[offset+1] << 8 ) ) * 1000;
+    offset += 2;
+    HTI_LOG_FORMAT( "Time to hold down = %d", iEventDelay.Int() );
+    iTapCount = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "Tap count = %d", iTapCount );
+    iActionDelay = ( aData[offset] + ( aData[offset+1] << 8 ) ) * 1000;
+    HTI_LOG_FORMAT( "Pause between taps = %d", iActionDelay.Int() );
+
+    // Start tapping
+    iReady = EFalse;
+    ChangePointerStateL();
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::HandleTapScreenL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::HandleTapAndDragL()
+// Handles a single drag and drop with straight line.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::HandleTapAndDragL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::HandleTapAndDragL" );
+
+    if ( aData.Length() != KTapCmdLength )
+        {
+        SendErrorMessageL( EInvalidParameters, KErrorInvalidParameters );
+        return;
+        }
+
+    TInt offset = 0;
+    iX = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "X coord down = %d", iX );
+    iY = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "Y coord down = %d", iY );
+    TInt xUp = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "X coord up = %d", xUp );
+    TInt yUp = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "Y coord up = %d", yUp );
+    iEventDelay = ( aData[offset] + ( aData[offset+1] << 8 ) ) * 1000;
+    HTI_LOG_FORMAT( "Drag time = %d", iEventDelay.Int() );
+
+    iReady = EFalse;
+    PointerDown();
+    iX = xUp;
+    iY = yUp;
+    iTimer.After( iStatus, iEventDelay );
+    SetActive();
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::HandleTapAndDragL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::HandleTapAndDragMultipointL()
+// Handles drawing one or more curvy lines.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::HandleTapAndDragMultipointL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::HandleTapAndDragMultipointL" );
+
+    TInt dataLength = aData.Length();
+    if ( dataLength < KDragMultiCmdMinLength || dataLength % 2 != 0 )
+        {
+        SendErrorMessageL( EInvalidParameters, KErrorInvalidParameters );
+        return;
+        }
+
+    TInt offset = 0;
+    iEventDelay = ( aData[offset] + ( aData[offset+1] << 8 ) ) * 1000;
+    offset += 2;
+    HTI_LOG_FORMAT( "Time between events = %d", iEventDelay.Int() );
+    iActionDelay = ( aData[offset] + ( aData[offset+1] << 8 ) ) * 1000;
+    offset += 2;
+    HTI_LOG_FORMAT( "Pause between lines = %d", iActionDelay.Int() );
+
+    if ( iCoords == NULL )
+        {
+        iCoords = new ( ELeave ) RArray<TInt>();
+        }
+    iCoords->Reset();
+
+    // Read integers from aData to the array, all integers are 2 bytes
+    while ( offset < dataLength )
+        {
+        iCoords->AppendL( aData[offset] + ( aData[offset + 1] << 8 ) );
+        offset += 2;
+        }
+
+    iReady = EFalse;
+    iTapCount = ( *iCoords )[0];
+    iCoords->Remove( 0 );
+    iX = ( *iCoords )[0];
+    iCoords->Remove( 0 );
+    iY = ( *iCoords )[0];
+    iCoords->Remove( 0 );
+    HTI_LOG_FORMAT( "Point count for first line = %d", iTapCount );
+    PointerDown();
+    iTapCount--;
+    iTimer.After( iStatus, iEventDelay );
+    SetActive();
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::HandleTapAndDragMultipointL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::HandlePointerDownOrUpL()
+// Handles pushing pointer down in one point or lifting it up.
+// This is synchronous operation and sends OK message right after the event
+// is simulated.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::HandlePointerDownOrUpL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::HandlePointerDownOrUpL" );
+    if ( aData.Length() != KSinglePointerCmdLength )
+        {
+        SendErrorMessageL( EInvalidParameters, KErrorInvalidParameters );
+        return;
+        }
+
+    // Parse the parameters - correct length is already verified
+    TInt offset = 0;
+    iX = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "X coord = %d", iX );
+    iY = aData[offset] + ( aData[offset+1] << 8 );
+    offset += 2;
+    HTI_LOG_FORMAT( "Y coord = %d", iY );
+
+    if ( iCommand == EPressPointerDown )
+        {
+        PointerDown();
+        }
+    else
+        {
+        PointerUp();
+        }
+    SendOkMsgL();
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::HandlePointerDownOrUpL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::ChangePointerStateL()
+// Decides whether to do  "pointer down" or "pointer up" event next or if
+// operation is complete.
+// This function is used by ETapScreen command.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::ChangePointerStateL()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::ChangePointerStateL" );
+    HTI_LOG_FORMAT( "Taps remaining = %d", iTapCount );
+    if ( iTapCount < 1 )
+        {
+        SendOkMsgL();
+        iReady = ETrue;
+        return;
+        }
+
+    if ( iState == EPointerUp )
+        {
+        PointerDown();
+        iTimer.After( iStatus, iEventDelay );
+        SetActive();
+        }
+    else if ( iState == EPointerDown )
+        {
+        PointerUp();
+        iTapCount--; // one tap done
+        if ( iTapCount > 0 ) // do we continue tapping?
+            {
+            iTimer.After( iStatus, iActionDelay );
+            SetActive();
+            }
+        else
+            {
+            SendOkMsgL();  // tapping done
+            iReady = ETrue;
+            }
+        }
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::ChangePointerStateL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::MoveToNextPointL()
+// Takes the next point from the coordinate array and initiates pointer moving
+// to that point.
+// This function is used by ETapAndDragMultipoint command and called from
+// the RunL().
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::MoveToNextPointL()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::MoveToNextPointL" );
+    HTI_LOG_FORMAT( "Points remaining for this line = %d", iTapCount );
+
+    if ( iTapCount == 0 ) // End of current line
+        {
+        PointerUp();
+        if ( iCoords->Count() < 5 ) // point count & at least 2 points
+            {
+            // This was the last line, we are done
+            SendOkMsgL();
+            iReady = ETrue;
+            }
+        else
+            {
+            // New line starts: take the point count of this line and
+            // first coordinates.
+            iTapCount = ( *iCoords )[0];
+            iCoords->Remove( 0 );
+            iX = ( *iCoords )[0];
+            iCoords->Remove( 0 );
+            iY = ( *iCoords )[0];
+            iCoords->Remove( 0 );
+            HTI_LOG_FORMAT( "Point count for new line = %d", iTapCount );
+            iTimer.After( iStatus, iActionDelay );
+            SetActive();
+            }
+        }
+
+    else  // Current line continues: take next point coords and move
+        {
+        iX = ( *iCoords )[0];
+        iCoords->Remove( 0 );
+        iY = ( *iCoords )[0];
+        iCoords->Remove( 0 );
+        PointerMove();
+        iTapCount--;
+        iTimer.After( iStatus, iEventDelay );
+        SetActive();
+        }
+
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::MoveToNextPointL" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::PointerDown()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::PointerDown()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::PointerDown" );
+    SimulatePointerEvent( TRawEvent::EButton1Down );
+    iState = EPointerDown;
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::PointerDown" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::PointerUp()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::PointerUp()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::PointerUp" );
+    SimulatePointerEvent( TRawEvent::EButton1Up );
+    iState = EPointerUp;
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::PointerUp" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::PointerMove()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::PointerMove()
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::PointerMove" );
+    SimulatePointerEvent( TRawEvent::EPointerMove );
+    iState = EPointerMoving;
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::PointerMove" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::SimulatePointerEvent()
+// Sends the pointer event as a raw event.
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::SimulatePointerEvent( TRawEvent::TType aType )
+    {
+    HTI_LOG_FUNC_IN( "CPointerEventHandler::SimulatePointerEvent" );
+    TRawEvent rawEvent;
+    rawEvent.Set( aType, iX, iY );
+    iWsSession.SimulateRawEvent( rawEvent );
+    iWsSession.Flush();
+    HTI_LOG_FUNC_OUT( "CPointerEventHandler::SimulatePointerEvent" );
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::SendOkMsgL()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::SendOkMsgL()
+    {
+    HTI_LOG_FUNC_IN("CPointerEventHandler::SendOkMsgL");
+
+    User::LeaveIfNull( iDispatcher );
+    TBuf8<1> response;
+    response.Append( EResultOk );
+    HBufC8* respH8 = response.AllocL();
+    User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
+        respH8, KKeyEventServiceUid ) );
+
+    HTI_LOG_FUNC_OUT("CPointerEventHandler::SendOkMsgL");
+    }
+
+// ----------------------------------------------------------------------------
+// CPointerEventHandler::SendErrorMessageL()
+// ----------------------------------------------------------------------------
+void CPointerEventHandler::SendErrorMessageL(
+        TInt aError, const TDesC8& aDescription )
+    {
+    HTI_LOG_FUNC_IN("CPointerEventHandler::SendErrorMessageL");
+    User::LeaveIfNull( iDispatcher );
+    User::LeaveIfError( iDispatcher->DispatchOutgoingErrorMessage(
+        aError, aDescription, KKeyEventServiceUid ) );
+    HTI_LOG_FUNC_OUT("CPointerEventHandler::SendErrorMessageL");
+    }
+
+// End of file