diff -r d39add9822e2 -r 5bfc169077b2 webengine/webkitutils/stmgesturefw/src/pinchgesturerecogniser.cpp --- 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 -#include "pinchgesturerecogniser.h" -#include "GenericSimpleGesture.h" -#include -#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 ; -}