--- /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 <aknappui.h>
+#include <e32base.h>
+
+#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<CCoeControl*>( 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