--- a/webengine/webkitutils/stmgesturefw/src/pinchgesturerecogniser.cpp Tue Feb 02 00:56:45 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,440 +0,0 @@
-/*
-* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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: Gesture helper implementation
-*
-*/
-#include <e32math.h>
-#include "pinchgesturerecogniser.h"
-#include "GenericSimpleGesture.h"
-#include <rt_uievent.h>
-#include "filelogger.h"
-#include "statemachine.h" // for stmUiEventEngine::Distance(dx,dy)
-
-using namespace stmGesture ;
-
-extern long Mm2Pixels(long mm) ;
-
-
-CPinchGestureRecogniser::CPinchGestureRecogniser(MGestureListener* aListener) :
- CGestureRecogniser(aListener)
-{
- m_pinching = false ;
- m_pinchingspeed = 3.5 ; // by default something suitable for capacitive
- m_holdseen = false ;
-}
-
-CPinchGestureRecogniser* CPinchGestureRecogniser::NewL(MGestureListener* aListener)
-{
- CPinchGestureRecogniser* self = new (ELeave) CPinchGestureRecogniser(aListener) ;
- return self;
-}
-
-CPinchGestureRecogniser::~CPinchGestureRecogniser()
-{
-}
-
-TGestureRecognitionState CPinchGestureRecogniser::recognise(int numOfActiveStreams,
- MGestureEngineIf* pge)
-{
- TGestureRecognitionState state = ENotMyGesture;
- // Check if we are enabled or not
- if (!m_gestureEnabled) return state ;
-
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: %d %d %d ", m_pinching, m_holdseen, numOfActiveStreams) ;
- }
-#if !defined(ADVANCED_POINTER_EVENTS)
- // Look at the events to see if it looks like pinch in single touch
- // WARNING: this code is a hack : in single touch capacitive touch device (like Alvin with 52.50) it works so-and-so,
- // because the pointer events were reported from the corners of the rectangle formed by two fingers pressing.
- // In resistive touch device like Tube or Ivalo the reported points are somewhere int he middle between the fingers
- // and jumping a lot, so it is very difficult to get it right.
- if (numOfActiveStreams == 1)
- {
- // Then look at the event stream, first we need to see a hold and then a fast jump
- const stmUiEventEngine::MUiEvent* puie = pge->getUiEvents(0);
- int countOfEvents = puie->countOfEvents() ;
- stmUiEventEngine::TUiEventCode eventCode = puie->Code() ;
-
- if (countOfEvents > 0 ) // how many events
- {
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: %d %d %d %d %d, m: %d b: %d",
- m_pinching, m_holdseen, numOfActiveStreams, countOfEvents, eventCode,
- int(m_m), int(m_b)) ;
- }
-
- if (m_pinching)
- {
- // We have entered pinching state, lets move one of the points unless it is a release
- if (eventCode == stmUiEventEngine::ERelease)
- {
- m_pinching = false ;
- m_holdseen = false ;
- }
- else
- {
- bool pointIgnored = true ; // for logging purposes
- int currentLength = m_loggingenabled ?
- stmUiEventEngine::Distance(m_pinchstart, m_pinchend) : 0;
-
- TPoint oStart(m_pinchstart) ;
- TPoint oEnd(m_pinchend) ;
- int difference = 0 ;
- state = ELockToThisGesture ;
- const TPoint& tp = puie->CurrentXY();
- // calculate the distance of the new point from the stored vector
- int d1 = ((m_pinchstart.iX-tp.iX)*(m_pinchstart.iX-tp.iX)) +
- ((m_pinchstart.iY-tp.iY)*(m_pinchstart.iY-tp.iY)) ;
- int d2 = ((m_pinchend.iX-tp.iX)*(m_pinchend.iX-tp.iX)) +
- ((m_pinchend.iY-tp.iY)*(m_pinchend.iY-tp.iY)) ;
- // check also if the Y coordinate happens to be near the hold point,
- // this seems to be the case at least with alvin, we keep getting two points,
- // where one is near the Y coordinate of the hold point
- int diffY = Abs(tp.iY-m_pinchstart.iY) ;
-
- if (d1 < d2 || diffY < 12)
- {
- // the detected point is near the first point,
- // or the detected point is about on the same horizontal line with the hold point
- // do not do anything, but keep the gesture
- }
- else
- {
- pointIgnored = false ;
- // the detected point is close to the other end, then adjust the stored vector
- int xd = m_pinchend.iX-tp.iX ;
- int yd = m_pinchend.iY-tp.iY ;
- if (xd < 0 ) xd = - xd ;
- if (yd < 0 ) yd = - yd ;
- // look which coordinate is closer to the original and use that
- if (xd < yd)
- {
- // calculate new point based on the X value
- m_pinchend.iX = tp.iX ;
- m_pinchend.iY = m_m*m_pinchend.iX + m_b ;
- if (m_pinchend.iY < 0) m_pinchend.iY = 0 ;
- }
- else
- {
- if (m_m != 0)
- {
- m_pinchend.iY = tp.iY ;
- m_pinchend.iX = (m_pinchend.iY - m_b)/m_m ;
- if (m_pinchend.iX <0 ) m_pinchend.iX = 0 ;
- }
- else
- {
- m_pinchend.iX = tp.iX ;
- m_pinchend.iY = m_m*m_pinchend.iX + m_b ;
- if (m_pinchend.iY < 0) m_pinchend.iY = 0 ;
- }
- }
- float newd = calculateDistance() ;
- // check if the difference is too big and adjust accordingly
- // the method also updates the m_ddistance
- difference = adjustPinchMove(m_ddistance, newd) ;
- // Now we have a pinch gesture with size as details
- stmGesture::TTwoPointGesture pgest(KUid, m_pinchstart, m_pinchend);
- pgest.setLogging(m_loggingenabled);
- pgest.setDetails(difference) ;
- // inform the listener
- m_listener->gestureEnter(pgest);
- }
- if (m_loggingenabled)
- {
- int newLength = stmUiEventEngine::Distance(m_pinchstart, m_pinchend);
- float speedX = puie->speedX() ;
- float speedY = puie->speedY() ;
-
- LOGARG("CPinchGestureRecogniser: %d: o: %d, n: %d, d: %d (%d,%d) " \
- "speed %f (%d,%d : %d,%d) (from: (%d,%d : %d,%d) (m: %f b: %f)",
- pointIgnored,
- currentLength, newLength, difference,
- tp.iX, tp.iY, double(speedX),
- m_pinchstart.iX, m_pinchstart.iY, m_pinchend.iX, m_pinchend.iY,
- oStart.iX, oStart.iY, oEnd.iX, oEnd.iY,
- double(m_m), double(m_b)) ;
-
- }
-
- }
- }
- else if (eventCode == stmUiEventEngine::EMove) // The last one is move and we were not pinching
- {
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: %d: num %d code %d", m_pinching, countOfEvents, eventCode);
- }
- stmUiEventEngine::MUiEvent* puieFirst = puie->previousEvent();
-
- // check if we have seen hold
- if (m_holdseen)
- {
- const TPoint& tp1 = puie->CurrentXY() ;
- float speedX = puie->speedX() ;
- float speedY = puie->speedY() ;
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: tp1: %d %d hold %d %d, speed %f",
- tp1.iX, tp1.iY,
- m_holdseenAtPos.iX, m_holdseenAtPos.iY, double(speedX) );
- }
- // is the speed extremely high so that it looks like other finger pressing in different location?
- if ( (speedX > m_pinchingspeed) || (speedY > m_pinchingspeed) )
- {
- TInt64 tstamp = puie->timestamp() ;
- TTime now(tstamp) ;
- TTimeIntervalMicroSeconds tim = now.MicroSecondsFrom(m_holdseenAtTime) ;
- m_pinching = true;
- m_pinchstart = m_holdseenAtPos;
- m_pinchend = tp1;
- calculateZoomingLine();
- m_ddistance = calculateDistance();
- state = ELockToThisGesture ; // NOTE: once pinch is started, it will stay until release
- // create the first pich gesture which does not yet resize anything
- stmGesture::TTwoPointGesture pgest(KUid, m_pinchstart, m_pinchend);
- pgest.setLogging(m_loggingenabled);
- pgest.setDetails(0) ;
- // inform the listener
- m_listener->gestureEnter(pgest);
- }
- }
- }
- }
- if (!m_pinching)
- {
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: not pinching %d", puie);
- }
- if (puie && puie->Code() == stmUiEventEngine::EHold) // The last one is hold and we were not pinching
- {
- m_holdseen = true;
- m_holdseenAtPos = puie->CurrentXY();
- m_holdseenAtTime = puie->timestamp() ;
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: hold seen at(%d, %d) at %Ld",
- m_holdseenAtPos.iX, m_holdseenAtPos.iY, m_holdseenAtTime.Int64());
- }
- }
- }
- if (puie && puie->Code() == stmUiEventEngine::ETouch) // The last one is touch
- {
- m_holdseen = false;
- }
- else if (puie && puie->Code() == stmUiEventEngine::ERelease) // The last one is release
- {
- m_holdseen = false;
- }
- }
-#else
- // This is the multi touch case: two event streams needs to be there; this is the real pinch zoom
- if (numOfActiveStreams == 2)
- {
- const stmUiEventEngine::MUiEvent* puie1 = pge->getUiEvents(0);
- const stmUiEventEngine::MUiEvent* puie2 = pge->getUiEvents(1);
- stmUiEventEngine::TUiEventCode eventCode1 = puie1->Code() ;
- stmUiEventEngine::TUiEventCode eventCode2 = puie2->Code() ;
-
- if (m_loggingenabled)
- {
- TPoint p1 = puie1->CurrentXY() ;
- TPoint p2 = puie2->CurrentXY() ;
- LOGARG("CPinchGestureRecogniser: two streams: %s at [%d,%d], %s at [%d,%d]",
- stmUiEventEngine::EventName(eventCode1), p1.iX, p1.iY,
- stmUiEventEngine::EventName(eventCode1), p2.iX, p2.iY
- ) ;
-
- }
-
-
- if (!m_pinching)
- {
- // This means we start pinching, the events can be any combination of ETouch, EMove, EHold
- if ( ( eventCode1 == stmUiEventEngine::ETouch ||
- eventCode1 == stmUiEventEngine::EMove ||
- eventCode1 == stmUiEventEngine::EHold
- ) &&
- ( eventCode2 == stmUiEventEngine::ETouch ||
- eventCode2 == stmUiEventEngine::EMove ||
- eventCode2 == stmUiEventEngine::EHold )
- )
- {
- // This is valid pinching start
- m_pinching = true ;
- // get the start and end position for the picnhing vector
- m_pinchstart = puie1->CurrentXY() ;
- m_pinchend = puie2->CurrentXY() ;
- calculateZoomingLine();
- m_ddistance = calculateDistance();
- state = ELockToThisGesture ; // NOTE: once pich is started, it will stay until release
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: pinch start: [%d,%d][%d,%d]",
- m_pinchstart.iX, m_pinchstart.iY, m_pinchend.iX, m_pinchend.iY) ;
-
- }
- // create the first pich gesture which does not yet resize anything
- stmGesture::TTwoPointGesture pgest(KUid, m_pinchstart, m_pinchend);
- pgest.setLogging(m_loggingenabled);
- pgest.setDetails(0) ;
- // inform the listener
- m_listener->gestureEnter(pgest);
- }
- else
- {
- // Not a valid pinching start, do nothing (maybe it were easier to just check if one of the events is ERelease)
- }
- }
- else
- {
- // We have entered pinching state, lets move one of the points unless it is a release
- if (eventCode1 == stmUiEventEngine::ERelease || eventCode2 == stmUiEventEngine::ERelease)
- {
- release(pge);
- }
- else
- {
- state = ELockToThisGesture ;
-
- // get the start and end position for the picnhing vector
- m_pinchstart = puie1->CurrentXY() ;
- m_pinchend = puie2->CurrentXY() ;
- float newd = calculateDistance() ;
- // check if the difference is too big and adjust accordingly
- // the method also updates the m_ddistance
- int difference = adjustPinchMove(m_ddistance, newd) ;
- // Now we have a pinch gesture with size
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: pinch: [%d,%d][%d,%d], diff %d",
- m_pinchstart.iX, m_pinchstart.iY, m_pinchend.iX, m_pinchend.iY, difference) ;
-
- }
-
- stmGesture::TTwoPointGesture pgest(KUid, m_pinchstart, m_pinchend);
- pgest.setLogging(m_loggingenabled);
- pgest.setDetails(difference) ;
- // inform the listener
- m_listener->gestureEnter(pgest);
- }
- }
-
- }
-#endif
-
- if (state == ENotMyGesture)
- {
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: NotMyGesture %d %d %d ",
- m_pinching, m_holdseen, numOfActiveStreams) ;
- }
- // if it was not our gesture, then the state can not be pinching...
- m_pinching = false ;
- }
- return state;
-}
-
-void CPinchGestureRecogniser::release(MGestureEngineIf* /*ge*/)
-{
- m_pinching = false ;
- m_listener->gestureExit(KUid) ;
-}
-
-/*!
- * Now that we know the two points where the zooming started, we move those points only along
- * the same line y = mx + b, so lets calculate m and b.
- */
-void CPinchGestureRecogniser::calculateZoomingLine()
-{
- int sX = m_pinchstart.iX ;
- int sY = m_pinchstart.iY ;
- int eX = m_pinchend.iX ;
- int eY = m_pinchend.iY ;
-
- if (eX == sX)
- {
- m_m = 0.f ;
- }
- else
- {
- m_m = float(eY-sY)/(eX-sX) ;
- }
- m_b = sY-(m_m*sX) ;
-}
-
-/*!
- * calculate the distance, return as float
- */
-float CPinchGestureRecogniser::calculateDistance()
-{
- double x = ((m_pinchstart.iX-m_pinchend.iX)*(m_pinchstart.iX-m_pinchend.iX))+
- ((m_pinchstart.iY-m_pinchend.iY)*(m_pinchstart.iY-m_pinchend.iY)) ;
- double ddist ;
- Math::Sqrt(ddist, x) ;
- return float(ddist) ;
-}
-
-/*!
- * Set the pinching speed as pixels / ms (meaning that in case of singletouch device
- * the other finger looks like the EMove UI event suddenly jumps to new location;
- * in resistive the new location is somewhere in the middle of the touches, in capacitive
- * the driver seems to report three or four points:
- * original (x,y), new (a,b) and also (a,y), sometimes (x,b)
- */
-void CPinchGestureRecogniser::setPinchingSpeed(float aSpeed) __SOFTFP
-{
- m_pinchingspeed = aSpeed ;
-}
-
-/*!
- * Adjust the pinch move so that it will not be too jumpy
- */
-int CPinchGestureRecogniser::adjustPinchMove(float& aPreviousDistance, float aNewDistance)
-{
- float diff = aNewDistance - aPreviousDistance ;
- float logdiff = diff ;
- if (diff < 0) diff = -diff ; // Note that the next calculations need the positive diff value, but keep the original in logdiff
- float changePercentage = (diff/aPreviousDistance)*100.f ;
- if (changePercentage > 10.f)
- {
- // change more than 10%, make at most 10%
- float newdiff = aPreviousDistance*0.1f ;
- if (aPreviousDistance > aNewDistance) newdiff = -newdiff ;
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: adjustPinchMove from %f to %f : was, now %f %f",
- double(logdiff), double(newdiff), double(aPreviousDistance), double(aNewDistance));
- }
-
- aPreviousDistance = aPreviousDistance + newdiff ;
- diff = newdiff ;
- }
- else
- {
- if (m_loggingenabled)
- {
- LOGARG("CPinchGestureRecogniser: adjustPinchMove from %f to %f : was, now %f %f",
- double(logdiff), double(diff), double(aPreviousDistance), double(aNewDistance));
- }
- aPreviousDistance = aNewDistance ; // accept the new value and update the new length
- diff = logdiff ; // put the original back (this is why the logdiff can not be Abs(diff)!
- }
- return (int)diff ;
-}