diff -r 000000000000 -r 2f259fa3e83a akntouchgesturefw/src/akntouchgesturefwimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/akntouchgesturefw/src/akntouchgesturefwimpl.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,461 @@ +/* +* 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: Touch gesture framework implementation. +* +*/ + +#include +#include + +#include "akntouchgesturefwimpl.h" +#include "akntouchgesturefwdefs.h" +#include "akntouchgesturefwevent.h" +#include "akntouchgesturefwrecognitionengine.h" + +using namespace AknTouchGestureFw; + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwImpl* CAknTouchGestureFwImpl::NewL( + MAknTouchGestureFwObserver& aObserver, + CCoeControl* aControl ) + { + CAknTouchGestureFwImpl* self = + CAknTouchGestureFwImpl::NewLC( aObserver, aControl ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwImpl* CAknTouchGestureFwImpl::NewLC( + MAknTouchGestureFwObserver& aObserver, + CCoeControl* aControl ) + { + CAknTouchGestureFwImpl* self = + new ( ELeave ) CAknTouchGestureFwImpl( aControl ); + CleanupStack::PushL( self ); + self->ConstructL( aObserver ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwImpl::~CAknTouchGestureFwImpl() + { + if ( iCoeEnv ) + { + iCoeEnv->RemoveForegroundObserver( *this ); + iCoeEnv->RemoveMessageMonitorObserver( *this ); + } + + delete iRecognitionEngine; + } + + +// --------------------------------------------------------------------------- +// Handles simulated pointer events. +// Used only for testing purposes. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::HandleSimulatedPointerEventL( + const TPointerEventData& pointerData ) + { + HandlePointerEventL( pointerData ); + + iSubscriberControl->HandlePointerEventL( pointerData.iPointerEvent ); + } + + +// --------------------------------------------------------------------------- +// Sets target control for window server events. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::SetSubscriberControlL( CCoeControl* aControl ) + { + CCoeControl* subsControl = aControl; + + CCoeControl* windowControl( subsControl ); + + while ( windowControl && !windowControl->OwnsWindow() ) + { + windowControl = windowControl->Parent(); + } + + if ( windowControl ) + { + iWindowControl = windowControl; + } + else + { + // The subscriber control or it's parents have no window, + // so there's no point to continue. + User::Leave( KErrNotFound ); + } + + iSubscriberControl = subsControl; + + EnableAdditionalEvents(); + } + + +// --------------------------------------------------------------------------- +// Sets the gesture interest. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::SetGestureInterestL( TUint aGestureGroups ) + { + TUint gestureInterest( EAknTouchGestureFwNoGroup ); + if ( aGestureGroups ) + { + gestureInterest = aGestureGroups; + } + + if ( !iMonitoringWs && + gestureInterest != EAknTouchGestureFwNoGroup ) + { + iCoeEnv->AddMessageMonitorObserverL( *this ); + iMonitoringWs = ETrue; + } + else if ( iMonitoringWs && + gestureInterest == EAknTouchGestureFwNoGroup ) + { + iCoeEnv->RemoveMessageMonitorObserver( *this ); + iMonitoringWs = EFalse; + } + + TRAPD( err, + iRecognitionEngine->SetGestureInterestL( gestureInterest ) ); + + // If setting the gesture interes fails then there's no need to + // monitor the WS events. + if ( err != KErrNone && iMonitoringWs ) + { + iCoeEnv->RemoveMessageMonitorObserver( *this ); + iMonitoringWs = EFalse; + + User::Leave( err ); + } + + EnableAdditionalEvents(); + } + + +// --------------------------------------------------------------------------- +// Returns the gesture groups which should be recognized. +// --------------------------------------------------------------------------- +// +TUint CAknTouchGestureFwImpl::GestureInterest() const + { + TUint gestureInterest( EAknTouchGestureFwNoGroup ); + if ( iRecognitionEngine ) + { + gestureInterest = iRecognitionEngine->GestureInterest(); + } + return gestureInterest; + } + + +// --------------------------------------------------------------------------- +// Defines gesture groups, which trigger tactile feedback automatically. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::SetFeedbackForGroupsL( TUint aGestureGroups ) + { + iRecognitionEngine->SetFeedbackForGroupsL( aGestureGroups ); + } + + +// --------------------------------------------------------------------------- +// Defines gesture types, which trigger tactile feedback automatically. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::SetFeedbackForTypesL( + TAknTouchGestureFwGroup aGestureGroup, + TUint aGestureTypesForTactile, + TUint aGestureTypesForAudio ) + { + iRecognitionEngine->SetFeedbackForTypesL( aGestureGroup, + aGestureTypesForTactile, aGestureTypesForAudio ); + } + + +// --------------------------------------------------------------------------- +// EnableTestingFeatures +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::EnableTestingFeatures() + { + iRecognitionEngine->EnableTestingFeatures(); + } + + +// ---------------------------------------------------------------------------- +// C++ Constructor +// --------------------------------------------------------------------------- +// +CAknTouchGestureFwImpl::CAknTouchGestureFwImpl( CCoeControl* aControl ) + : + iMonitoringWs( EFalse ), + iCoeEnv( CCoeEnv::Static() ), + iSubscriberControl( aControl ), + iWindowControl( NULL ), + iRecognitionEngine( NULL ) + { + } + + +// --------------------------------------------------------------------------- +// Symbian second-phase constructor. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::ConstructL( + MAknTouchGestureFwObserver& aObserver ) + { + SetSubscriberControlL( iSubscriberControl ); + + iRecognitionEngine = + CAknTouchGestureFwRecognitionEngine::NewL( aObserver, + iSubscriberControl ); + + iCoeEnv->AddForegroundObserverL( *this ); + } + + +// --------------------------------------------------------------------------- +// Handles pointer events. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::HandlePointerEventL( + const TPointerEventData& aPointerData ) + { +#ifdef GFW_DEBUG_TRACE_INPUTOUTPUT + AknTouchGestureFwUtils::DumpPointerEvent( aEvent, aPointerData.iSimulated ); +#endif // GFW_DEBUG_TRACE_INPUTOUTPUT + + const TPointerEvent event = aPointerData.iPointerEvent; + TInt pointerNumber = 0; + if ( event.IsAdvancedPointerEvent() ) + { + pointerNumber = event.AdvancedPointerEvent()->PointerNumber(); + } + + __ASSERT_ALWAYS( pointerNumber >= 0, User::Invariant() ); + __ASSERT_ALWAYS( pointerNumber <= 1, User::Invariant() ); + + iRecognitionEngine->HandlePointerEventL( aPointerData ); + } + + +// --------------------------------------------------------------------------- +// Cancels ongoing recognition. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::CancelRecognition() + { + iRecognitionEngine->CancelRecognizing(); + } + + +// --------------------------------------------------------------------------- +// Enables the necessary events for the subscriber control's window. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::EnableAdditionalEvents() + { + // Additional pointer events are needed for the following gesture groups + TUint gestureInterest( GestureInterest() ); + TBool multiEventsNeeded = gestureInterest & EAknTouchGestureFwGroupPinch; + TBool dragEventsNeeded = + gestureInterest & ( EAknTouchGestureFwGroupFlick | + EAknTouchGestureFwGroupDrag | + EAknTouchGestureFwGroupPinch ); + + // Enables drag events and advanced pointer events for window if needed + if ( iWindowControl ) + { + RDrawableWindow* window = iWindowControl->DrawableWindow(); + if ( window ) + { + if ( dragEventsNeeded ) + { + window->PointerFilter( EPointerFilterDrag, 0 ); + } + if ( multiEventsNeeded ) + { + window->EnableAdvancedPointers(); + } + if ( dragEventsNeeded || multiEventsNeeded ) + { + // Set pointer grab when drag or multi pointer events are + // needed to enable gesture recognition outside gesture control. + window->SetPointerGrab( ETrue ); + } + } + } + } + + +// --------------------------------------------------------------------------- +// Checks if pointer event is targeted to the gesture control. +// --------------------------------------------------------------------------- +// +TBool CAknTouchGestureFwImpl::PointerEventTargetedToControl( + CCoeControl* aTargetControl, + TPointerEvent& aEvent ) const + { + if ( !aTargetControl ) + { + return EFalse; + } + + TBool targetedToControl( EFalse ); + TBool eventInControl( + iSubscriberControl->Rect().Contains( aEvent.iPosition ) ); + + // Check if target control is gesture control's window control. + targetedToControl = aTargetControl == iWindowControl; + + // Check that pointer is in gesture control area. + if ( targetedToControl && + aEvent.iType == TPointerEvent::EButton1Down ) + { + targetedToControl = eventInControl; + } + + // Check if pointer is targeted to child window that is on gesture + // control area. + else if ( !targetedToControl && eventInControl ) + { + CCoeControl* windowControl( aTargetControl ); + while ( windowControl ) + { + windowControl = windowControl->Parent(); + if ( windowControl == iWindowControl ) + { + targetedToControl = ETrue; + ConvertPositionToControlWindow( + aTargetControl->DrawableWindow(), + aEvent.iPosition ); + break; + } + } + } + + return targetedToControl; + } + + +// --------------------------------------------------------------------------- +// Converts position in window area according to control window coordinates. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::ConvertPositionToControlWindow( + RDrawableWindow* aWindow, + TPoint& aPosition ) const + { + if ( aWindow ) + { + TPoint targetPosition( aWindow->AbsPosition() ); + TPoint windowPosition( + iWindowControl->DrawableWindow()->AbsPosition() ); + aPosition.iX = aPosition.iX + targetPosition.iX - windowPosition.iX; + aPosition.iY = aPosition.iY + targetPosition.iY - windowPosition.iY; + } + } + + +// --------------------------------------------------------------------------- +// Called when the application gains foreground. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::HandleGainingForeground() + { +#ifdef GFW_DEBUG_TRACE_INPUTOUTPUT + _LIT( KAknTouchGainForeground, "[GFW] IN GAIN FOREGROUND" ); + RDebug::Print( KAknTouchGainForeground ); +#endif + + if ( !iMonitoringWs && GestureInterest() != EAknTouchGestureFwNoGroup ) + { + TRAP_IGNORE( iCoeEnv->AddMessageMonitorObserverL( *this ) ); + iMonitoringWs = ETrue; + } + } + + +// --------------------------------------------------------------------------- +// Called when the application loses foreground. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::HandleLosingForeground() + { +#ifdef GFW_DEBUG_TRACE_INPUTOUTPUT + _LIT( KAknTouchLostForeground, "[GFW] IN LOST FOREGROUND" ); + RDebug::Print( KAknTouchLostForeground ); +#endif + + // Reset framework state because it might be possible that + // pointer is down when framework loses background. + // In this situation corresponding up-event is never received + // and framework stays to wrong state (assuming pointer is still down) + // without resetting it. + CancelRecognition(); + + if ( iMonitoringWs ) + { + iCoeEnv->RemoveMessageMonitorObserver( *this ); + iMonitoringWs = EFalse; + } + } + + +// --------------------------------------------------------------------------- +// Handles window server messages. +// --------------------------------------------------------------------------- +// +void CAknTouchGestureFwImpl::MonitorWsMessage( const TWsEvent& aEvent ) + { + if ( aEvent.Type() == EEventPointer ) + { + CCoeControl* targetControl = + reinterpret_cast( aEvent.Handle() ); + TAdvancedPointerEvent event( *aEvent.Pointer() ); + TBool targetedToControl( PointerEventTargetedToControl( + targetControl, event ) ); + + TPointerEventData pointerData( event, + event.PointerNumber(), + aEvent.Time(), + EFalse, + targetedToControl ); + + TRAP_IGNORE( HandlePointerEventL( pointerData ) ); + } + else if ( aEvent.Type() == EEventScreenDeviceChanged ) + { + // Cancel recognition if layout changes + CancelRecognition(); + } + } + +// End of File