ginebra2/GWebTouchNavigation.cpp
changeset 0 1450b09d0cfd
child 3 0954f5dd2cd0
child 5 0f2326c2a325
equal deleted inserted replaced
-1:000000000000 0:1450b09d0cfd
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "GWebTouchNavigation.h"
       
    20 #include "qwebpage.h"
       
    21 #include "qwebframe.h"
       
    22 #include "qapplication.h"
       
    23 #include "qwebelement.h"
       
    24 #include "GWebContentViewWidget.h"
       
    25 #include "GWebContentView.h"
       
    26 #include <QGraphicsSceneMouseEvent>
       
    27 #include <QTimer>
       
    28 #include <qmath.h>
       
    29 #include <QDebug>
       
    30 #include <QGraphicsView>
       
    31 
       
    32 #include "webcontentview.h"
       
    33 #include "wrtBrowserUtils.h"
       
    34 #include "ChromeWidget.h"
       
    35 #include <qdebug.h>
       
    36 
       
    37 
       
    38 #define LONG_PRESS_DURATION 500
       
    39 
       
    40 const int KFlickSpeed = 400;
       
    41 const qreal PI = 3.1415926535897932;
       
    42 const qreal KAngleTolerance = 30;
       
    43 const int KAnimationTimeout = 40;
       
    44 const qreal KDecelerationFactor = 0.8;
       
    45 const int KMilliSecond = 1000;
       
    46 const int KThresholdForRightToLeftMotion = 100;  // 100 pixels
       
    47 const int KThresholdForLeftToRightMotion = -100; // 100 pixels
       
    48 const int XAlignVal = 10;
       
    49 const int KDecelerationTimer = 125; //Decelerate only if flicked/swiped after KDecelerationTimer milli seconds after last drag event
       
    50 
       
    51 const int KDoubleClickTimeOut = 400;
       
    52 const QPoint KFocussPoint(5, 50);
       
    53 const int KTouchThresholdX = 20;
       
    54 const int KTouchThresholdY = 20;
       
    55 const int KPanThreshold = 2;
       
    56 const int KThreshHoldValForLink = 10;
       
    57 const qreal KDeccelaration = 1000.00;
       
    58 const int KDefaultViewportWidth = 980;
       
    59 const int KDefaultPortraitScaleWidth = 540;
       
    60 
       
    61 const int KKineticTimeout = 60;
       
    62 
       
    63 static const int KStartPanDistance = 50;
       
    64 static const int KWaitForClickTimeoutMS = 200;
       
    65 //The amount of pixels to try to pan before pan mode unlocks
       
    66 static const int KPanModeChangeDelta = 100;
       
    67 
       
    68 
       
    69 namespace GVA {
       
    70 
       
    71 /*!
       
    72     \class WebTouchNavigation
       
    73     \since cwrt 1.0
       
    74     \brief cwrt navigation.
       
    75 
       
    76     \sa WebNavigation, WebHtmlTabIndexedNavigation, WebCursorNavigation, WebDirectionalNavigation
       
    77 */
       
    78 GWebTouchNavigation::GWebTouchNavigation(QWebPage* webPage,GWebContentViewWidget* view)
       
    79 : m_webPage(webPage)
       
    80 , m_view(view)
       
    81 , m_frame(0)
       
    82 , m_doubleClickTimer(0)
       
    83 , m_pressEvent(0)
       
    84 , m_scrollTimer(0)
       
    85 , m_releaseEvent(0)
       
    86 , m_focusedBlockPt(-1, -1)
       
    87 , m_ishighlighted(false)
       
    88 , m_offset(0)
       
    89 , m_longPressTimer(0)
       
    90 , m_finalzoomfactor(0)
       
    91 , m_kineticTimer(0)
       
    92 , m_isPanning(false)
       
    93 , m_enabled(true)
       
    94 , m_isLoading(false)
       
    95 {
       
    96         install();
       
    97         connect(m_view, SIGNAL(BlockFocusChanged(QPoint)), this, SLOT(BlockFocusChanged(QPoint)));
       
    98         connect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted()));
       
    99         connect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool)));
       
   100 }
       
   101 
       
   102 /*!
       
   103 */
       
   104 GWebTouchNavigation::~GWebTouchNavigation() 
       
   105 {
       
   106     disconnect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired()));    
       
   107     if (m_doubleClickTimer) {
       
   108         m_doubleClickTimer->stop();
       
   109         delete m_doubleClickTimer;
       
   110     }
       
   111     disconnect(m_scrollTimer, SIGNAL(timeout()),this,SLOT(pan()));
       
   112     delete m_scrollTimer;
       
   113     
       
   114     disconnect(m_kineticTimer, SIGNAL(timeout()),this,SLOT(kineticScroll()));
       
   115     delete m_kineticTimer;
       
   116     uninstall();
       
   117 }
       
   118 
       
   119 void GWebTouchNavigation::install()
       
   120 {
       
   121     m_view->installEventFilter(this);
       
   122 }
       
   123 
       
   124 void GWebTouchNavigation::BlockFocusChanged(QPoint pt)
       
   125 {
       
   126 	m_focusedBlockPt = pt;
       
   127 }
       
   128 
       
   129 void GWebTouchNavigation::uninstall()
       
   130 {
       
   131     if (m_view)
       
   132         m_view->removeEventFilter(this);
       
   133 }
       
   134 
       
   135 bool GWebTouchNavigation::eventFilter(QObject *object, QEvent *event)
       
   136 {
       
   137     if (object != m_view || !enabled())
       
   138         return false;
       
   139 
       
   140     switch (event->type()) {
       
   141         case QEvent::MouseButtonPress:
       
   142             if (static_cast<QMouseEvent *>(event)->buttons() & Qt::LeftButton) {
       
   143                 mousePressEvent(static_cast<QMouseEvent *>(event)->pos());
       
   144                 return true;
       
   145             }
       
   146             break;
       
   147         case QEvent::MouseMove:
       
   148             if (static_cast<QMouseEvent *>(event)->buttons() & Qt::LeftButton) {
       
   149                 QPoint diff = m_touchPosition - static_cast<QMouseEvent*>(event)->globalPos();
       
   150                 mouseMoveEvent(static_cast<QMouseEvent*>(event)->pos(), diff);
       
   151                 return true;
       
   152             }
       
   153             break;
       
   154         case QEvent::MouseButtonRelease:
       
   155             mouseReleaseEvent(static_cast<QMouseEvent*>(event)->pos());
       
   156             return true;
       
   157         case QEvent::MouseButtonDblClick:
       
   158             mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)->pos());
       
   159             return true;
       
   160         case QEvent::GraphicsSceneMousePress:
       
   161             if (static_cast<QGraphicsSceneMouseEvent*>(event)->buttons() & Qt::LeftButton) {
       
   162                 mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint());
       
   163                 emit mouseEvent(QEvent::GraphicsSceneMousePress);
       
   164                 return true;
       
   165             }
       
   166             break;
       
   167         case QEvent::GraphicsSceneMouseMove:
       
   168             if (static_cast<QGraphicsSceneMouseEvent *>(event)->buttons() & Qt::LeftButton) {
       
   169                 QPoint diff = static_cast<QGraphicsSceneMouseEvent*>(event)->lastScenePos().toPoint() - static_cast<QGraphicsSceneMouseEvent*>(event)->scenePos().toPoint();
       
   170                 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint(), diff);
       
   171                 return true;
       
   172             }
       
   173             break;
       
   174         case QEvent::GraphicsSceneMouseRelease: 
       
   175             mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint());
       
   176             emit mouseEvent(QEvent::GraphicsSceneMouseRelease);
       
   177             return true;
       
   178             break;
       
   179         case QEvent::GraphicsSceneMouseDoubleClick:
       
   180             mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(event)->pos().toPoint());
       
   181             emit mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
       
   182             return true;
       
   183             break;
       
   184         default:
       
   185             break;
       
   186     }
       
   187     return false;
       
   188 }
       
   189 
       
   190 void GWebTouchNavigation::stopScrolling()
       
   191 {
       
   192 	if (m_scrollTimer && m_scrollTimer->isActive()) {
       
   193 	    m_scrollTimer->stop();
       
   194 	    m_scrollDelta = QPoint(0,0);
       
   195 	}
       
   196 	
       
   197 	if (m_kineticTimer && m_kineticTimer->isActive()) {
       
   198 	    m_kineticTimer->stop();
       
   199 	    m_kineticSpeed.setX(0.0);
       
   200 	    m_kineticSpeed.setY(0.0);
       
   201 	}
       
   202 }
       
   203 
       
   204 
       
   205 void GWebTouchNavigation::pan()
       
   206 {
       
   207 	if (m_scrollDelta.x() != 0 || m_scrollDelta.y() != 0) {
       
   208             scrollCurrentFrame(-m_scrollDelta.x(), m_scrollDelta.y());
       
   209 	    m_scrollDelta = QPoint(0,0);
       
   210 	}
       
   211 }
       
   212 
       
   213 #define DECELERATION 0.0002 
       
   214 
       
   215 void GWebTouchNavigation::kineticScroll()
       
   216 {
       
   217 	qreal decelX = m_kineticSpeed.x() > 0 ? -DECELERATION : DECELERATION;
       
   218 	qreal decelY = m_kineticSpeed.y() > 0 ? -DECELERATION : DECELERATION;
       
   219 	qreal dx = 0;
       
   220 	qreal dy = 0;
       
   221 	qreal vx = 0;
       
   222 	qreal vy = 0;
       
   223 	
       
   224 	m_kineticScrollTime += m_actualTime.elapsed();
       
   225 	
       
   226 	if (m_kineticSpeed.x()) {
       
   227 		vx = m_kineticSpeed.x() + decelX * m_kineticScrollTime;
       
   228 		if (vx * m_kineticSpeed.x() < 0) {
       
   229 			dx = 0;
       
   230 			vx = 0;
       
   231 		}
       
   232 		else {
       
   233 	        dx = m_kineticScrollTime * m_kineticSpeed.x() + 
       
   234 		        0.5 * decelX * m_kineticScrollTime * m_kineticScrollTime;
       
   235 		}
       
   236 	}
       
   237 	
       
   238 	if (m_kineticSpeed.y()) {
       
   239 		vy = m_kineticSpeed.y() + decelY * m_kineticScrollTime;
       
   240 		if (vy * m_kineticSpeed.y() < 0) {
       
   241 			dy = 0;
       
   242 			vy = 0;
       
   243 		}
       
   244 		else {
       
   245 		    dy = m_kineticScrollTime * m_kineticSpeed.y() + 
       
   246 			     0.5 * decelY * m_kineticScrollTime * m_kineticScrollTime;
       
   247 		}
       
   248 	}
       
   249 		
       
   250 	QPoint scrollPos = m_frame->scrollPosition();
       
   251 	QPoint distPos = m_initialScrollPos + QPointF(dx, dy).toPoint();
       
   252 	
       
   253 	if (vx != 0 || vy != 0) {
       
   254             setCurrentFrameScrollPosition(distPos);
       
   255 	}
       
   256     
       
   257 	if ((vx == 0 && vy == 0) || scrollPos == m_frame->scrollPosition()) {
       
   258     	stopScrolling();
       
   259     }
       
   260 
       
   261 }
       
   262 
       
   263 
       
   264 
       
   265 /*!
       
   266     Scrolls QWebFrame to the given position
       
   267     \sa QWebFrame::scroll()
       
   268 */
       
   269 void GWebTouchNavigation::scrollFrame(const QPoint& diff)
       
   270 {
       
   271     if (qAbs(diff.x()) < KPanThreshold && qAbs(diff.y()) < KPanThreshold)
       
   272         return;
       
   273 		else if(m_dragPoints.size() == 1) {	
       
   274         //WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view);
       
   275         m_view->setBlockElement(QWebElement());
       
   276 		}
       
   277         
       
   278 		if(!m_isPanning) {
       
   279         qreal dy = qAbs(diff.y());
       
   280         qreal dx = qAbs(diff.x());
       
   281         if (dy > KStartPanDistance || dx > KStartPanDistance
       
   282         || m_delayedPressMoment.elapsed() > KWaitForClickTimeoutMS) {
       
   283             //get the scroll direction
       
   284             Direction scrollDir = findDirectionWithAngle(diff);
       
   285             if(scrollDir == UP || scrollDir == DOWN)
       
   286                 startPanGesture(VerticalPan);
       
   287             else if(scrollDir == LEFT || scrollDir == RIGHT)
       
   288                 startPanGesture(HorizontalPan);
       
   289             else
       
   290                 startPanGesture(RandomPan);
       
   291             m_isPanning = true;
       
   292         }
       
   293     }
       
   294 
       
   295 		if (m_isPanning) {
       
   296 				m_scrolled= false;
       
   297 				m_frame = getNextScrollableFrame(diff);
       
   298 				QPoint scrollPosition = m_frame->scrollPosition();
       
   299 				if (diff.manhattanLength())
       
   300 						panBy(diff);            
       
   301 				
       
   302 				m_scrolled = (scrollPosition != m_frame->scrollPosition());
       
   303 		}
       
   304 }
       
   305 
       
   306 void GWebTouchNavigation::startPanGesture(PanDirection directionHint) {
       
   307     emit startingPanGesture((int)directionHint);
       
   308     m_panDirection = directionHint;
       
   309     m_panModeResidue = QPointF(0., 0.);
       
   310 }
       
   311 
       
   312 void GWebTouchNavigation::panBy(const QPointF& delta) {
       
   313     
       
   314     m_panModeResidue += delta;
       
   315 
       
   316     if (qAbs(m_panModeResidue.x()) > KPanModeChangeDelta)
       
   317         m_panDirection = HorizontalPan;
       
   318     
       
   319     if (qAbs(m_panModeResidue.y()) > KPanModeChangeDelta)
       
   320         m_panDirection = VerticalPan;
       
   321    
       
   322     if(qAbs(m_panModeResidue.x()) > KPanModeChangeDelta 
       
   323         && qAbs(m_panModeResidue.y()) > KPanModeChangeDelta)
       
   324         m_panDirection = RandomPan;
       
   325     
       
   326     QPointF p;
       
   327     if(m_panDirection == HorizontalPan)
       
   328         p.setX(delta.x());
       
   329     if(m_panDirection == VerticalPan)
       
   330         p.setY(delta.y());
       
   331     if(m_panDirection == RandomPan) {
       
   332         p.setX(delta.x());     
       
   333         p.setY(delta.y());
       
   334     }
       
   335         
       
   336     scrollCurrentFrame(p.x(),p.y());
       
   337 }
       
   338 
       
   339 void GWebTouchNavigation::highlightableElement(QMouseEvent* ev) {
       
   340     m_anchorElement = getClosestAnchorElement(ev);
       
   341 }
       
   342 
       
   343 inline int xInRect(const QRect& r, int x)
       
   344 {
       
   345     return std::min(std::max(x, r.x()), r.x() + r.width());
       
   346 }
       
   347 
       
   348 inline int yInRect(const QRect& r, int y)
       
   349 {
       
   350     return std::min(std::max(y, r.y()), r.y() + r.height());
       
   351 }
       
   352 
       
   353 bool GWebTouchNavigation::traverseNextNode(QWebElement parentNode,QWebElement& nextNode) 
       
   354 { 
       
   355     if (!parentNode.firstChild().isNull()) {
       
   356         nextNode = parentNode.firstChild();
       
   357         return true;
       
   358     }
       
   359            
       
   360     if (!parentNode.nextSibling().isNull()) {
       
   361         nextNode = parentNode.nextSibling();
       
   362         return true;
       
   363     }
       
   364 
       
   365     QWebElement n = parentNode;
       
   366     while (!n.isNull() && n.nextSibling().isNull()) 
       
   367         n = n.parent (); 
       
   368     
       
   369     if (!n.isNull()) {
       
   370         nextNode = n.nextSibling();
       
   371         return true;
       
   372     }
       
   373 
       
   374     return false; 
       
   375 } 
       
   376 
       
   377 
       
   378 QWebElement GWebTouchNavigation::getClosestAnchorElement(QMouseEvent* ev)
       
   379 {   
       
   380     QWebElement webElement;
       
   381     QWebHitTestResult htRes = getHitTestResult(ev);
       
   382     QWebElement hitElement = htRes.element();
       
   383     //check whether hit test returns a link element
       
   384     if(!htRes.linkElement().isNull()) {
       
   385         webElement = htRes.linkElement();              
       
   386 		m_higlightedPos = ev->pos();
       
   387         m_ishighlighted = true;
       
   388     }
       
   389     //get the closet anchor element
       
   390     else {
       
   391 		QPoint docPoint = (m_touchPosition + m_frame->scrollPosition());
       
   392         int dist = 99999999;
       
   393         QWebElement result;
       
   394         QWebElement ele = m_webPage->currentFrame()->documentElement();
       
   395         do {
       
   396             if(ele.tagName().compare("a",Qt::CaseInsensitive) == 0 ) {       
       
   397                 QRect r = ele.geometry();
       
   398                 if(r.contains(docPoint)) {
       
   399                     dist = 0;
       
   400                     result = ele;
       
   401                     break;
       
   402                 }
       
   403 
       
   404                 int x = xInRect(r, docPoint.x());
       
   405                 int y = yInRect(r, docPoint.y());
       
   406                 int d = (docPoint.x() - x) * (docPoint.x() - x) + (docPoint.y() - y) * (docPoint.y() - y);
       
   407                 if (dist > d) {
       
   408                     dist = d;
       
   409                     result = ele;
       
   410                 }
       
   411             }                       
       
   412         }while(traverseNextNode(ele,ele));
       
   413 
       
   414 //        WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view);
       
   415 		// check if we are close enough and calcualte with zoom factor.
       
   416         if (dist< (KThreshHoldValForLink/m_view->zoomFactor())) {
       
   417             QRect r = result.geometry();
       
   418             r.translate(2,2); 
       
   419             r.setWidth(2+2); 
       
   420             r.setHeight(2+2); 
       
   421             webElement = result;
       
   422             m_higlightedPos = QPoint(xInRect(r, docPoint.x()), yInRect(r, docPoint.y())) - m_frame->scrollPosition(); 
       
   423             m_ishighlighted = true;
       
   424             QPoint centerpt = webElement.geometry().center();
       
   425             m_offset = (docPoint.x()- centerpt.x())*(docPoint.x()- centerpt.x()) + (docPoint.y()- centerpt.y())*(docPoint.y()- centerpt.y());
       
   426             
       
   427         }
       
   428     }
       
   429     return webElement;
       
   430 }
       
   431 
       
   432 /*!
       
   433     Sends a mouse press event to QWebPage
       
   434 */
       
   435 void GWebTouchNavigation::mousePressEvent(const QPoint& pos)
       
   436 {
       
   437     m_delayedPressMoment.start();
       
   438     // stop deceleration and don't send further events to engine if scroll timer is active
       
   439     if(m_scrollTimer && m_scrollTimer->isActive()) {
       
   440         m_prevPoint.setX(0);
       
   441         m_prevPoint.setY(0);
       
   442         m_scrollDistance.setX(0);
       
   443         m_scrollDistance.setY(0);
       
   444         
       
   445         m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS
       
   446         m_scrolled = false;
       
   447         m_ishighlighted = false;
       
   448         m_higlightedPos = m_touchPosition = pos;
       
   449         m_frame = m_webPage->frameAt(pos);
       
   450         if (!m_frame)
       
   451               m_frame = m_webPage->currentFrame(); 
       
   452           
       
   453         m_dragPoints.clear();
       
   454           
       
   455         DragPoint dragPoint;
       
   456         dragPoint.iPoint = m_touchPosition;
       
   457         dragPoint.iTime = QTime::currentTime();
       
   458         m_dragPoints.append(dragPoint);
       
   459         m_offset = 0;
       
   460         
       
   461         m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, m_touchPosition, Qt::LeftButton, Qt::LeftButton, getEventModifier(m_touchPosition));
       
   462         m_scrollTimer->stop();
       
   463         return;
       
   464     }
       
   465     
       
   466     if (m_doubleClickTimer) {
       
   467         // If there is another click event almost on the same region 
       
   468         // as the previous click before doubleClick timeout 
       
   469         // Consider it as double click.
       
   470         if (m_doubleClickTimer->isActive() && m_pressEvent) {
       
   471             QPoint diff = m_pressEvent->pos() - pos;
       
   472             if (qAbs(diff.x()) < KTouchThresholdX && qAbs(diff.y()) < KTouchThresholdY) {           
       
   473                 mouseDoubleClickEvent(pos);
       
   474                 return;
       
   475             }
       
   476         }
       
   477         m_doubleClickTimer->stop();
       
   478     } else {
       
   479         m_doubleClickTimer = new QTimer(this);
       
   480         connect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired()));    
       
   481     }
       
   482 
       
   483     //Clear the previous press and release events.
       
   484     if (m_pressEvent) {
       
   485         delete m_pressEvent;
       
   486         m_pressEvent = NULL;
       
   487     }
       
   488     
       
   489     if (m_releaseEvent) {
       
   490         delete m_releaseEvent;
       
   491         m_releaseEvent = NULL;
       
   492     }
       
   493 
       
   494     m_doubleClickTimer->start(KDoubleClickTimeOut);
       
   495     m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, getEventModifier(pos));
       
   496 }
       
   497 
       
   498 void GWebTouchNavigation::handleMousePressEvent(QMouseEvent* ev)
       
   499 {
       
   500     m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS
       
   501     if(!m_longPressTimer){
       
   502         delete m_longPressTimer;
       
   503         m_longPressTimer = 0;
       
   504     }
       
   505     startTimer();
       
   506     m_scrolled = false;
       
   507     m_ishighlighted = false;
       
   508     m_higlightedPos = m_touchPosition = ev->pos();
       
   509     m_frame = m_webPage->frameAt(ev->pos());
       
   510     if (!m_frame)
       
   511         m_frame = m_webPage->currentFrame(); 
       
   512     
       
   513     m_dragPoints.clear();
       
   514     
       
   515     DragPoint dragPoint;
       
   516     dragPoint.iPoint = m_touchPosition;
       
   517     dragPoint.iTime = QTime::currentTime();
       
   518     m_dragPoints.append(dragPoint);
       
   519 
       
   520 	m_offset = 0;
       
   521 	
       
   522     highlightableElement(ev);
       
   523     getFocusedElement();		
       
   524 
       
   525     //send a mouse press
       
   526     QMouseEvent iev(ev->type(), m_touchPosition, ev->button(), ev->buttons(), getEventModifier(m_higlightedPos));
       
   527     m_webPage->event(&iev);
       
   528 }
       
   529 
       
   530 void GWebTouchNavigation::doubleClickTimerExpired()
       
   531 {   
       
   532     handleMousePressEvent(m_pressEvent);
       
   533 
       
   534     delete m_pressEvent;
       
   535     m_pressEvent = NULL;
       
   536     
       
   537     if (m_releaseEvent) {
       
   538         handleMouseReleaseEvent(m_releaseEvent);
       
   539 
       
   540 		//clear release event
       
   541 		delete m_releaseEvent;
       
   542         m_releaseEvent = NULL;
       
   543     }
       
   544 	if (m_doubleClickTimer && m_doubleClickTimer->isActive())
       
   545         m_doubleClickTimer->stop();
       
   546 }
       
   547 
       
   548 bool GWebTouchNavigation::canDehighlight(QMouseEvent* ev)
       
   549  {
       
   550     bool checkDehighlight = false;  
       
   551     QPoint pt = ev->pos() + m_frame->scrollPosition();
       
   552     
       
   553     if(m_scrolled && m_ishighlighted) {
       
   554         checkDehighlight = true;
       
   555     }
       
   556     else if(!m_scrolled && m_ishighlighted) {
       
   557         QRect rect = m_anchorElement.geometry();
       
   558 
       
   559         if(m_anchorElement.geometry().contains(pt)) {
       
   560             checkDehighlight = false;
       
   561         }
       
   562         else if(m_offset){
       
   563             QPoint centerpt = m_anchorElement.geometry().center();
       
   564             int newoffset = (pt.x()- centerpt.x())*(pt.x()- centerpt.x()) + (pt.y()- centerpt.y())*(pt.y()- centerpt.y());
       
   565         
       
   566             if(newoffset <= m_offset ) {
       
   567                  m_offset = newoffset;
       
   568                  checkDehighlight = false;
       
   569             }
       
   570             else {
       
   571                 m_offset =0;
       
   572                 checkDehighlight = true;
       
   573             }
       
   574         }
       
   575         else {
       
   576             checkDehighlight = true;
       
   577         }
       
   578     }
       
   579     return checkDehighlight;
       
   580 }
       
   581  void  GWebTouchNavigation::dehighlight(QMouseEvent* ev)
       
   582 {
       
   583     m_higlightedPos = QPoint(0,0);
       
   584     m_ishighlighted = false;
       
   585     QMouseEvent iev(QEvent::MouseButtonPress,m_higlightedPos,ev->button(), ev->buttons(), ev->modifiers());
       
   586     m_webPage->event(&iev);
       
   587 }
       
   588 
       
   589 void GWebTouchNavigation::handleHighlightChange(QMouseEvent* ev)
       
   590 {
       
   591     if (!canDehighlight(ev)) return;
       
   592 
       
   593     dehighlight(ev);
       
   594 }
       
   595 
       
   596 /*!
       
   597     Scrolls the frame
       
   598     \sa scrollFrame()
       
   599 */
       
   600 void GWebTouchNavigation::mouseMoveEvent(const QPoint& pos, const QPoint& diff)
       
   601 {
       
   602 	
       
   603     if (m_pressEvent){
       
   604     	QPoint diff2 = m_pressEvent->pos() - pos;
       
   605       if (qAbs(diff2.x()) < KTouchThresholdX && qAbs(diff2.y()) < KTouchThresholdY)
       
   606         return;    
       
   607     }	
       
   608        
       
   609     if (m_doubleClickTimer && m_doubleClickTimer->isActive()) {
       
   610         //send mousePressEvent
       
   611         m_doubleClickTimer->stop();
       
   612         handleMousePressEvent(m_pressEvent);
       
   613         delete m_pressEvent;
       
   614         m_pressEvent = NULL;
       
   615     }
       
   616 
       
   617     stopTimer();
       
   618     QMouseEvent tmpEv(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
   619     handleHighlightChange(&tmpEv);
       
   620 
       
   621     scrollFrame(diff);
       
   622 
       
   623 		//m_touchPosition = pos;
       
   624 		DragPoint dragPoint;
       
   625 		dragPoint.iPoint = pos;
       
   626 		dragPoint.iTime = QTime::currentTime();
       
   627 		m_dragPoints.append(dragPoint);
       
   628 
       
   629 		QTime now(QTime::currentTime());
       
   630 		m_lastMoveEventTime.setHMS(now.hour(),now.minute(), now.second(), now.msec());
       
   631 
       
   632 		while (m_dragPoints.size() > 4)
       
   633 				m_dragPoints.removeFirst();
       
   634     
       
   635 }
       
   636 
       
   637 /*!
       
   638     If WebCanvas or QWebFrame were scrolled starts the deceleration alogrithm
       
   639     Otherwise sends the mouse release event to QWebPage
       
   640     \sa startDeceleration()
       
   641 */
       
   642 void GWebTouchNavigation::mouseReleaseEvent(const QPoint& pos)
       
   643 {
       
   644     if(m_isPanning)
       
   645         m_isPanning = false;
       
   646     if (m_doubleClickTimer && m_doubleClickTimer->isActive()) {
       
   647         m_releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
   648         return;
       
   649     }
       
   650     //mouseReleaseEvent is called in two cases. 1. Double click, 2. Mouse Drag
       
   651     //m_releaseEvent is not null only in Mouse double click
       
   652     //So delete m_releaseEvent only in double click case.
       
   653     //Send release event in mouse move case
       
   654     if (m_releaseEvent) {
       
   655         delete m_releaseEvent ;
       
   656         m_releaseEvent = NULL;
       
   657     } else {
       
   658         QMouseEvent tmpEv(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
   659         handleMouseReleaseEvent(&tmpEv);    
       
   660     }
       
   661 }
       
   662 Qt::KeyboardModifier GWebTouchNavigation::getEventModifier(const QPoint& pos)
       
   663 {
       
   664     QWebFrame *frame = m_webPage->frameAt(pos);
       
   665     if (!frame)
       
   666           frame = m_webPage->currentFrame(); 
       
   667     QWebHitTestResult htr = frame->hitTestContent(pos);
       
   668     if (htr.element().tagName().toLower().compare("select")==0  && htr.element().hasAttribute("multiple"))
       
   669         return Qt::ControlModifier;
       
   670     return Qt::NoModifier;
       
   671 }
       
   672 
       
   673 void GWebTouchNavigation::handleMouseReleaseEvent(QMouseEvent* ev)
       
   674 {
       
   675     m_frame = m_webPage->frameAt(ev->pos());
       
   676     if (!m_frame)
       
   677         m_frame = m_webPage->currentFrame(); 
       
   678     assert(m_frame);
       
   679     
       
   680      stopTimer();
       
   681      if (m_scrolled) {
       
   682         int msecs = 0;
       
   683         if (!m_lastMoveEventTime.isNull()) {
       
   684             //Start deceleration only if the delta since last drag event is less than threshold
       
   685             QTime now(QTime::currentTime());
       
   686             msecs = m_lastMoveEventTime.msecsTo(now);
       
   687             m_lastMoveEventTime.setHMS(0,0,0,0);
       
   688         }
       
   689         if (msecs < KDecelerationTimer) {
       
   690             if( isFlick()) {
       
   691                 updateFlickScrollDistance();
       
   692             }
       
   693             else {
       
   694                 QRect enclosingRect = findEnclosingBlock(ev);
       
   695                 QPoint blockDocPt(enclosingRect.x(), enclosingRect.y());
       
   696                 QPoint blockCanvasPoint(blockDocPt - m_frame->scrollPosition());
       
   697                 calculateActualScrollDistance();
       
   698                 int thresholdCheckVal = blockCanvasPoint.x() - m_actualScrollDistance.x();
       
   699                 setNewScrollDistance(blockCanvasPoint, thresholdCheckVal);
       
   700             }
       
   701             startScrollTimer();
       
   702         }
       
   703     } else {
       
   704         QMouseEvent iev = m_ishighlighted ? 
       
   705         QMouseEvent(ev->type(), m_higlightedPos, ev->button(), ev->buttons(), getEventModifier(m_higlightedPos)) :
       
   706         QMouseEvent(QEvent::MouseButtonRelease, m_touchPosition, ev->button(), ev->buttons(), getEventModifier(m_touchPosition));
       
   707         m_webPage->event(&iev);
       
   708 #if defined __SYMBIAN32__
       
   709 // FIXME Remove this, it will be fixed Qt 4.6.3 ? 
       
   710         if (ev->button() == Qt::LeftButton) {
       
   711             QWebHitTestResult htr = m_frame->hitTestContent(ev->pos());
       
   712             if (htr.isContentEditable()) {
       
   713                 QEvent vkbEvent(QEvent::RequestSoftwareInputPanel);
       
   714                 QList<QGraphicsView*> views = m_view->scene()->views();
       
   715                 QWidget* view = qobject_cast<QWidget*>(views.value(0));
       
   716                 if (view)
       
   717                     QApplication::sendEvent(view, &vkbEvent);
       
   718             }
       
   719         }
       
   720 #endif
       
   721     }
       
   722 }
       
   723 
       
   724 void GWebTouchNavigation::mouseDoubleClickEvent(const QPoint& pos)
       
   725 {
       
   726     
       
   727     if(m_doubleClickTimer && !m_doubleClickTimer->isActive())
       
   728         return;
       
   729     else if(m_doubleClickTimer)
       
   730         m_doubleClickTimer->stop();
       
   731 
       
   732     //If the page is already scrolling(because of a previous doubletap)
       
   733     //we need to stop the timer before we start scrolling the new block again.
       
   734     if (m_scrollTimer && m_scrollTimer->isActive())
       
   735         m_scrollTimer->stop();
       
   736 
       
   737     QMouseEvent tmpEv(QEvent::MouseButtonDblClick, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
   738     handleDoubleClickEvent(&tmpEv);
       
   739 }
       
   740 
       
   741 void GWebTouchNavigation::handleDoubleClickEvent(QMouseEvent* ev)
       
   742 {
       
   743     QPoint imageFocusPoint;
       
   744     QWebHitTestResult hitTest = getHitTestResult(ev);
       
   745     
       
   746     QWebElement block = hitTest.element();
       
   747 
       
   748     if (block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == ""))
       
   749         block = hitTest.enclosingBlockElement();
       
   750 
       
   751     QWebFrame* frame = m_webPage->frameAt(ev->pos());
       
   752     m_frame = (frame) ? frame : m_webPage->mainFrame();
       
   753     
       
   754     QRect enclosingRect = block.geometry();
       
   755           
       
   756     QPoint blockCanvasPt = QPoint(enclosingRect.topLeft()) - m_frame->scrollPosition();            
       
   757     //WebContentWidget* view = qobject_cast<WebContentWidget*>(m_view);
       
   758     m_view->setBlockElement(QWebElement());
       
   759 	if(m_focusedBlockPt == blockCanvasPt) {
       
   760 		m_focusedBlockPt.setX(-1);
       
   761 		m_focusedBlockPt.setY(-1);
       
   762 		qreal m_Ratiox = (qreal) blockCanvasPt.x() / block.geometry().width();
       
   763 		qreal m_Ratioy = (qreal) blockCanvasPt.y() / block.geometry().height();
       
   764         m_view->setZoomFactor(m_view->initialScale());
       
   765 		QPoint m_InfocusBlockPt = QPoint(block.geometry().topLeft()) - m_webPage->mainFrame()->scrollPosition(); 
       
   766 		m_webPage->currentFrame()->scroll(m_InfocusBlockPt.x() - (m_Ratiox * block.geometry().width()),
       
   767 																					m_InfocusBlockPt.y() - (m_Ratioy * block.geometry().height()));
       
   768         m_finalzoomfactor = 0;
       
   769 	}else {     
       
   770         if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) {
       
   771             m_finalzoomfactor   = (qreal) (m_webPage->viewportSize().width() - 10) * m_view->zoomFactor();
       
   772         	m_finalzoomfactor = (qreal) m_finalzoomfactor / (enclosingRect.width());
       
   773         	QString str;
       
   774         	str.setNum(m_finalzoomfactor,'f',2);
       
   775 			m_finalzoomfactor = str.toDouble();
       
   776 		}else {																																     			
       
   777 			qreal factor;
       
   778             factor = 1/m_view->initialScale();
       
   779             int boundW = block.geometry().width() * factor/m_view->zoomFactor();
       
   780             int boundH = block.geometry().height() * factor/m_view->zoomFactor();
       
   781 			qreal factorw = 0.0,factorh = 0.0 ;
       
   782 	     		
       
   783 			if( boundW > m_webPage->viewportSize().width())
       
   784 				factorw = (qreal)(m_webPage->viewportSize().width()-5)/ block.geometry().width();
       
   785 			
       
   786 			if(boundH > m_webPage->viewportSize().height())
       
   787 				factorh = (qreal)(m_webPage->viewportSize().height()-5)/ block.geometry().height();			
       
   788 
       
   789 			if( (factorw == 0.0) && (factorh == 0.0))
       
   790 				;
       
   791 			else if(factorw == 0.0)
       
   792                 factor = factorh * m_view->zoomFactor();
       
   793 			else if(factorh == 0.0)
       
   794                 factor = factorw * m_view->zoomFactor();
       
   795 			else {
       
   796                 factor = ((factorh < factorw) ? factorh : factorw) * m_view->zoomFactor();
       
   797 			}	
       
   798 								
       
   799 			QString str;
       
   800 			str.setNum(factor,'f',2);
       
   801 			factor = str.toDouble();	
       
   802 							
       
   803 			if(m_finalzoomfactor != factor) 				    				  		     	
       
   804 				m_finalzoomfactor = factor;
       
   805 		}
       
   806 
       
   807     
       
   808         if (m_finalzoomfactor != m_view->zoomFactor()) {
       
   809             m_view->setZoomFactor(m_finalzoomfactor);
       
   810             m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition(); 
       
   811     
       
   812 			if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) 
       
   813             	scrollCurrentFrame(m_focusedBlockPt.x() - KFocussPoint.x() , m_focusedBlockPt.y() - KFocussPoint.y());
       
   814         	else {
       
   815             	if((m_webPage->viewportSize().width() - block.geometry().width()) > 0)
       
   816                 	imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2);
       
   817             	else
       
   818                 	imageFocusPoint.setX(0);
       
   819             
       
   820             	if((m_webPage->viewportSize().height() - block.geometry().height()) > 0)
       
   821                 	imageFocusPoint.setY((m_webPage->viewportSize().height() - block.geometry().height())/2);
       
   822             	else
       
   823                 	imageFocusPoint.setY(0);
       
   824             
       
   825             	scrollCurrentFrame(m_focusedBlockPt.x() - imageFocusPoint.x() , m_focusedBlockPt.y() - imageFocusPoint.y());
       
   826         	}
       
   827     
       
   828 			m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition();      
       
   829         } else { 
       
   830 			//Get doc size and current bottom right view corner point in document
       
   831             QSize viewSize = m_webPage->viewportSize();
       
   832             QSize contentSize = m_frame->contentsSize();
       
   833             QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition();
       
   834     		QPoint docFocusPoint;
       
   835 
       
   836     		if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) 
       
   837         		docFocusPoint = KFocussPoint + m_frame->scrollPosition();
       
   838     		else {
       
   839         		if((m_webPage->viewportSize().width() - block.geometry().width()) > 0)                                  
       
   840            			 imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2);
       
   841        			else
       
   842             		imageFocusPoint.setX(0);
       
   843     
       
   844         		if((m_webPage->viewportSize().height() - block.geometry().height()) > 0)    
       
   845             		imageFocusPoint.setY((m_webPage->viewportSize().height()- block.geometry().height())/2);
       
   846         		else
       
   847             		imageFocusPoint.setY(0);
       
   848     
       
   849         		docFocusPoint = imageFocusPoint + m_frame->scrollPosition();
       
   850    			}
       
   851 
       
   852             m_focusedBlockPt = QPoint(block.geometry().x(), block.geometry().y());
       
   853             m_scrollDistance.setX(m_focusedBlockPt.x() - docFocusPoint.x());
       
   854             m_scrollDistance.setY(m_focusedBlockPt.y() - docFocusPoint.y());
       
   855 
       
   856             QPoint scrollableDistance(0, 0);
       
   857             QPoint viewStartPoint = QPoint(0,0) + m_frame->scrollPosition();
       
   858     
       
   859    			if(m_scrollDistance.x() < 0)
       
   860              	scrollableDistance.setX(viewStartPoint.x());
       
   861    			 else
       
   862              	scrollableDistance.setX(contentSize.width() - documentViewPoint.x());
       
   863             
       
   864 
       
   865    			if(m_scrollDistance.y() < 0)
       
   866         		scrollableDistance.setY(viewStartPoint.y());
       
   867     		 else
       
   868 				scrollableDistance.setY(contentSize.height() - documentViewPoint.y());
       
   869 
       
   870 			if(abs(m_scrollDistance.x()) > abs(scrollableDistance.x())){
       
   871                 //m_scrollDistance.x() >= 0 means scroll from right to left
       
   872         		if(m_scrollDistance.x() >= 0)
       
   873                 	m_focusedBlockPt.setX(m_focusedBlockPt.x() - abs(scrollableDistance.x()));
       
   874                 //m_scrollDistance.x() < 0 means scroll from left to right
       
   875         		else
       
   876                 	m_focusedBlockPt.setX(m_focusedBlockPt.x() + abs(scrollableDistance.x()));
       
   877              } else
       
   878                 m_focusedBlockPt.setX(docFocusPoint.x());
       
   879 
       
   880 			if (abs(m_scrollDistance.y()) > abs(scrollableDistance.y())){
       
   881         		if(m_scrollDistance.y() >= 0)
       
   882                 	m_focusedBlockPt.setY(m_focusedBlockPt.y() - abs(scrollableDistance.y()));
       
   883         		else
       
   884                 	m_focusedBlockPt.setY(m_focusedBlockPt.y() + abs(scrollableDistance.y()));
       
   885             }
       
   886             else
       
   887             	m_focusedBlockPt.setY(docFocusPoint.y());
       
   888             
       
   889             m_focusedBlockPt = m_focusedBlockPt - m_frame->scrollPosition();
       
   890             startScrollTimer();
       
   891         }
       
   892     m_view->setBlockElement(block);
       
   893 	}
       
   894 }
       
   895 
       
   896 /*!
       
   897     Returns the next scrollable frame in the frame tree give the x,y position
       
   898 */
       
   899 QWebFrame* GWebTouchNavigation::getNextScrollableFrame(const QPoint& pos)
       
   900 {
       
   901     QWebFrame* frame = m_frame;
       
   902     while (frame) {
       
   903         if (pos.x() > 0) {
       
   904             if (frame->scrollBarValue(Qt::Horizontal) < frame->scrollBarMaximum(Qt::Horizontal))
       
   905                 break;
       
   906         }
       
   907         else if (pos.x() < 0) {
       
   908             if (frame->scrollBarValue(Qt::Horizontal) > frame->scrollBarMinimum(Qt::Horizontal))
       
   909                 break;
       
   910         }
       
   911 
       
   912         if (pos.y() > 0) {
       
   913             if (frame->scrollBarValue(Qt::Vertical) < frame->scrollBarMaximum(Qt::Vertical))
       
   914                 break;
       
   915         }
       
   916         else if (pos.y() < 0) {
       
   917             if (frame->scrollBarValue(Qt::Vertical) > frame->scrollBarMinimum(Qt::Vertical))
       
   918                 break;
       
   919         }
       
   920         frame = frame->parentFrame();
       
   921     }
       
   922     return (frame)?frame:m_webPage->mainFrame();
       
   923 }
       
   924 
       
   925 /*
       
   926 Starts the timer for scrolling smoothly to the destination location .
       
   927 The timer will do the decelaration while scrolling
       
   928 */
       
   929 void GWebTouchNavigation::startScrollTimer()
       
   930 {
       
   931     if(!m_scrollTimer) {
       
   932         m_scrollTimer = new QTimer(this);
       
   933         connect(m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollToEdge()));
       
   934     }
       
   935     m_scrollTimer->stop();
       
   936     m_scrollTimer->start(KAnimationTimeout);
       
   937 }
       
   938 
       
   939 /*
       
   940 Update the scroll distance for flick gesture. Update the scroll distance upto the edge of the page
       
   941 */
       
   942 void GWebTouchNavigation::updateFlickScrollDistance()
       
   943 {
       
   944 	m_initialSpeed = speed();
       
   945 	m_initialSpeed.setX(qAbs(m_initialSpeed.x()));
       
   946 	m_initialSpeed.setY(qAbs(m_initialSpeed.y()));
       
   947 	m_flickDirection = findDirectionWithAngle(m_dragPoints.first().iPoint - m_dragPoints.last().iPoint);
       
   948 	m_scrollDistance.setX((m_initialSpeed.x() * m_initialSpeed.x())/( 2 * KDeccelaration));
       
   949 	m_scrollDistance.setY((m_initialSpeed.y() * m_initialSpeed.y())/( 2 * KDeccelaration));
       
   950 	  
       
   951     m_scrollDistance.setX(m_view->zoomFactor() * m_scrollDistance.x() / m_view->initialScale());
       
   952     m_scrollDistance.setY(m_view->zoomFactor() * m_scrollDistance.y() / m_view->initialScale());
       
   953 
       
   954 	QSize viewSize = m_webPage->viewportSize();
       
   955   	QSize contentSize = m_frame->contentsSize();
       
   956   	QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition();
       
   957   	QPoint documentTouchPoint = m_touchPosition + m_frame->scrollPosition();;
       
   958    
       
   959 	switch(m_flickDirection)
       
   960     {
       
   961         case DOWN : 
       
   962                     m_scrollDistance.setX(0);
       
   963 					m_scrollDistance.setY(-(m_scrollDistance.y()));
       
   964 										
       
   965 					if(m_scrollDistance.y() < -(documentTouchPoint.y() - m_touchPosition.y()))
       
   966 						m_scrollDistance.setY(-(documentTouchPoint.y() - m_touchPosition.y()));
       
   967                     break;
       
   968         case UP :
       
   969                     m_scrollDistance.setX(0);
       
   970                     if(m_scrollDistance.y() > (contentSize.height() - documentViewPoint.y()))
       
   971                     	m_scrollDistance.setY(contentSize.height() - documentViewPoint.y());
       
   972                     break;
       
   973         case RIGHT:
       
   974                     m_scrollDistance.setX(-(m_scrollDistance.x()));
       
   975                     if(m_scrollDistance.x() < -(documentTouchPoint.x() - m_touchPosition.x()))
       
   976 						m_scrollDistance.setX(-(documentTouchPoint.x() - m_touchPosition.x()));
       
   977                     m_scrollDistance.setY(0);
       
   978                     break;
       
   979         case LEFT:              
       
   980 					m_scrollDistance.setY(0);
       
   981 					if(m_scrollDistance.x() > (contentSize.width() - documentViewPoint.x()))
       
   982 						m_scrollDistance.setX(contentSize.width() - documentViewPoint.x());
       
   983 					break;
       
   984         case BOTTOMRIGHT:
       
   985                     m_scrollDistance.setX(-(m_scrollDistance.x()));
       
   986 					m_scrollDistance.setY(-(m_scrollDistance.y())); 
       
   987 					if(m_scrollDistance.x() <  -(documentTouchPoint.x()-m_touchPosition.x()))
       
   988             			m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x()));
       
   989                     if(m_scrollDistance.y() < -((documentTouchPoint.y()-m_touchPosition.y())/2))
       
   990                     	m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2));
       
   991 					break;
       
   992         case BOTTOMLEFT: 
       
   993 					m_scrollDistance.setY(-(m_scrollDistance.y()));  	
       
   994 					if(m_scrollDistance.x() > contentSize.width()-documentViewPoint.x())
       
   995                    		m_scrollDistance.setX(contentSize.width()-documentViewPoint.x());
       
   996                    	if(m_scrollDistance.y() < (-((documentTouchPoint.y()-m_touchPosition.y())/2)))
       
   997                     	m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2));
       
   998                     break;
       
   999         case TOPLEFT:
       
  1000                     if(m_scrollDistance.x() > (contentSize.width()-documentViewPoint.x()))
       
  1001                    		m_scrollDistance.setX(contentSize.width()-documentViewPoint.x());
       
  1002                    	if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2))
       
  1003                     	m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2);
       
  1004                     break;      
       
  1005         case TOPRIGHT:
       
  1006                     m_scrollDistance.setX(-(m_scrollDistance.x()));
       
  1007                     if(m_scrollDistance.x() < (-(documentTouchPoint.x()-m_touchPosition.x())))
       
  1008                     	m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x()));
       
  1009                     if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2))
       
  1010 						m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2);
       
  1011                     break;
       
  1012     }
       
  1013 }
       
  1014 
       
  1015 /*
       
  1016 Distinguishes b/w swipe and flick
       
  1017 */
       
  1018 bool GWebTouchNavigation::isFlick() 
       
  1019 {
       
  1020     bool flick = false;
       
  1021     QPoint moveSpeed = speed();
       
  1022     int xSpeed = moveSpeed.x();
       
  1023     int ySpeed = moveSpeed.y();
       
  1024      
       
  1025     flick = (qAbs(xSpeed) > KFlickSpeed || 
       
  1026              qAbs(ySpeed) > KFlickSpeed);
       
  1027  
       
  1028     return flick;
       
  1029 }
       
  1030 
       
  1031 /*
       
  1032 Calculates the speed of te scroll along x-axis and y-axis
       
  1033 */
       
  1034 QPoint GWebTouchNavigation::speed() 
       
  1035 {
       
  1036     // Speed is only evaluated at the end of the swipe
       
  1037     QPoint dragSpeed(0,0);
       
  1038     qreal time =  dragTime() / KMilliSecond;
       
  1039     if (time > 0) {
       
  1040         QPoint distance = currentPos() - previousPos();
       
  1041         dragSpeed.setX((distance.x()) / time);
       
  1042         dragSpeed.setY((distance.y()) / time);
       
  1043     }
       
  1044     return dragSpeed;
       
  1045 }
       
  1046 
       
  1047 /*
       
  1048 Returns the last point in the m_dragPoints list
       
  1049 */
       
  1050 QPoint GWebTouchNavigation::currentPos()
       
  1051 {
       
  1052     return m_dragPoints[m_dragPoints.size()-1].iPoint;
       
  1053 }
       
  1054 
       
  1055 /*
       
  1056 Returns the first point in the m_dragPoints list
       
  1057 */
       
  1058 QPoint GWebTouchNavigation::previousPos()
       
  1059 {
       
  1060     return m_dragPoints[0].iPoint;
       
  1061 }
       
  1062 
       
  1063 /*
       
  1064 Finds the time difference b/w the first and last dragpoint
       
  1065 */
       
  1066 qreal GWebTouchNavigation::dragTime() const
       
  1067 {
       
  1068     if(m_dragPoints.isEmpty())
       
  1069         return 0.0;
       
  1070     else
       
  1071         return  m_dragPoints[0].iTime.msecsTo(m_dragPoints[m_dragPoints.size()-1].iTime);
       
  1072 }
       
  1073 
       
  1074 /*!
       
  1075 Find the flick direction with respect to angle of flick
       
  1076 */
       
  1077 Direction GWebTouchNavigation::findDirectionWithAngle(const QPoint& diff)
       
  1078 {
       
  1079     Direction direction;
       
  1080     int xDelta = -diff.x();
       
  1081     int yDelta = -diff.y();
       
  1082 
       
  1083     qreal angle = findAngle(xDelta, yDelta);
       
  1084     if(isNear(angle, 60.0, 120.0)) {
       
  1085          direction = DOWN;
       
  1086      }
       
  1087     else if(isNear(angle, 150.0, 210.0)) {
       
  1088         direction = LEFT;
       
  1089     }
       
  1090     else if(isNear(angle, 240.0, 300.0)) {
       
  1091         direction = UP;
       
  1092     }
       
  1093     else if(360.0 - KAngleTolerance <= angle || angle <= KAngleTolerance) {
       
  1094         direction = RIGHT;
       
  1095     }
       
  1096     else if(isNear(angle, 30.0, 60.0)) {
       
  1097         direction = BOTTOMRIGHT;
       
  1098     }
       
  1099     else if(isNear(angle, 120.0, 150.0)) {
       
  1100         direction = BOTTOMLEFT;
       
  1101     }
       
  1102     else if(isNear(angle, 210.0, 240.0)) {
       
  1103         direction = TOPLEFT;
       
  1104     }
       
  1105     else if(isNear(angle, 300.0, 330.0)) {
       
  1106         direction = TOPRIGHT;
       
  1107     }
       
  1108 
       
  1109     return direction;
       
  1110 }
       
  1111 
       
  1112 /*
       
  1113 Check the angle is in the range of aMinAngle and aMaxAngle
       
  1114 */
       
  1115 bool GWebTouchNavigation::isNear(qreal angleUnderTest, qreal minAngle, qreal maxAngle)
       
  1116 {
       
  1117     return (minAngle < angleUnderTest) &&  (angleUnderTest <= maxAngle);
       
  1118 }
       
  1119 
       
  1120 /*
       
  1121 Find the angle from x and y displacement
       
  1122 */
       
  1123 qreal GWebTouchNavigation::findAngle(const int& xDelta,const int& yDelta)
       
  1124 {
       
  1125     qreal angle = 0;
       
  1126     qreal hypotenuse = qSqrt(xDelta*xDelta + yDelta*yDelta);
       
  1127 
       
  1128     if(hypotenuse != 0) {
       
  1129         angle = qAcos(xDelta / hypotenuse);
       
  1130 
       
  1131         if(yDelta < 0) { 
       
  1132             angle = (2 * PI) - angle;
       
  1133         }
       
  1134     }
       
  1135 
       
  1136     return (angle * 180) / PI;
       
  1137 }
       
  1138 
       
  1139 int GWebTouchNavigation::roundOff(qreal num) 
       
  1140 {
       
  1141 	return (num + 0.5);
       
  1142 }
       
  1143 
       
  1144 /*
       
  1145 Finds out the enclosing block 
       
  1146 */
       
  1147 QRect GWebTouchNavigation::findEnclosingBlock(QMouseEvent* ev)
       
  1148 {
       
  1149     QWebHitTestResult htr = getHitTestResult(ev);
       
  1150     QRect rect = htr.enclosingBlockElement().geometry();
       
  1151     return rect;
       
  1152 }
       
  1153 
       
  1154 /*
       
  1155 Gets the hitTestResult for a particular event
       
  1156 */
       
  1157 QWebHitTestResult GWebTouchNavigation::getHitTestResult(QMouseEvent* ev)
       
  1158 {
       
  1159     QPoint pt = ev->pos();
       
  1160     QWebFrame* frame = m_webPage->frameAt(pt);
       
  1161     frame = (frame) ? frame : m_webPage->mainFrame();
       
  1162     QWebHitTestResult htr = frame->hitTestContent(pt);
       
  1163     return htr;
       
  1164 }
       
  1165 
       
  1166 /*
       
  1167 Finds out the scroll distance associated with a swipe 
       
  1168 */
       
  1169 void GWebTouchNavigation::calculateActualScrollDistance()
       
  1170 {
       
  1171     m_actualScrollDistance.setX(0);
       
  1172     m_actualScrollDistance.setY(0);
       
  1173     if (!m_dragPoints.isEmpty()) {
       
  1174         QPoint distance = previousPos() - currentPos();
       
  1175         if (qAbs(distance.x()) > 0 || qAbs(distance.y()) > 0) {
       
  1176             m_actualScrollDistance = distance / m_dragPoints.size() * 2;
       
  1177         }
       
  1178     }
       
  1179 }
       
  1180 
       
  1181 /*
       
  1182 In the case of slow swipe, if the destination location lies within the threshold area, then
       
  1183 we need to align the block to te left edge of the mobile screen. This method finds out the 
       
  1184 new scroll distance
       
  1185 */
       
  1186 void GWebTouchNavigation::setNewScrollDistance(QPoint blockCanvasPoint, int thresholdCheckVal)
       
  1187 {
       
  1188     m_scrollDistance.setX(m_actualScrollDistance.x());
       
  1189     m_scrollDistance.setY(m_actualScrollDistance.y());
       
  1190     if(blockCanvasPoint.x() > 0) {
       
  1191         //Checks whether the block falls within the threshold after right to left swipe
       
  1192         if( (thresholdCheckVal <  KThresholdForRightToLeftMotion) && (thresholdCheckVal > 0)) {
       
  1193             //if the block is within the threshold range already and the user tries
       
  1194             //to swipe from left to right , then let it move to right. Dont try to
       
  1195             //snap to the left edge .
       
  1196             if(m_actualScrollDistance.x() > 0) {
       
  1197                 m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal);
       
  1198             }
       
  1199         }
       
  1200     }
       
  1201     else {
       
  1202         //Checks whether the block falls within the threshold after left to right swipe
       
  1203         if( (thresholdCheckVal >  KThresholdForLeftToRightMotion) && (thresholdCheckVal < 0)) {
       
  1204             //if the block is within the threshold range already and the user tries
       
  1205             //to swipe from right to left , then let it move to left. Dont try to
       
  1206             //snap to the left edge .
       
  1207             if (m_actualScrollDistance.x() < 0) {
       
  1208                 m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal);
       
  1209             }
       
  1210         }
       
  1211         
       
  1212     }
       
  1213 }
       
  1214 
       
  1215 
       
  1216 /*
       
  1217 SLOT associated with the timer to adjust the scroll to the edge
       
  1218 */
       
  1219 void GWebTouchNavigation::scrollToEdge()
       
  1220 {
       
  1221     m_prevPoint.setX(m_scrollDistance.x());
       
  1222     m_prevPoint.setY(m_scrollDistance.y());
       
  1223 
       
  1224     m_scrollDistance.setX(m_scrollDistance.x() * KDecelerationFactor);
       
  1225     m_scrollDistance.setY(m_scrollDistance.y() * KDecelerationFactor);
       
  1226  
       
  1227     //round off the values
       
  1228     m_scrollDistance.setX(roundOff(m_scrollDistance.x()));
       
  1229     m_scrollDistance.setY(roundOff(m_scrollDistance.y()));
       
  1230 
       
  1231     int diffX = m_prevPoint.x() - m_scrollDistance.x();
       
  1232     int diffY = m_prevPoint.y() - m_scrollDistance.y();
       
  1233 
       
  1234     if (((m_scrollDistance.x() == 0) && (m_scrollDistance.y() == 0)) 
       
  1235          || ((diffX == 0) && (diffY == 0))) {
       
  1236         scrollCurrentFrame(m_prevPoint.x(), m_prevPoint.y());
       
  1237         m_scrollTimer->stop();
       
  1238         return;
       
  1239     }
       
  1240     scrollCurrentFrame(diffX, diffY);
       
  1241 }
       
  1242 void GWebTouchNavigation::timerControl()
       
  1243 {
       
  1244 	stopTimer();// stop timer as soon as timeout 
       
  1245     emit longPressEvent();
       
  1246 }
       
  1247 void GWebTouchNavigation::startTimer()
       
  1248 {
       
  1249     m_longPressTimer = new QTimer(this);
       
  1250     connect(m_longPressTimer,SIGNAL(timeout()),this,SLOT(timerControl()));
       
  1251     m_longPressTimer->start(LONG_PRESS_DURATION);
       
  1252 }
       
  1253 void GWebTouchNavigation::stopTimer()
       
  1254 {
       
  1255     if(m_longPressTimer){
       
  1256             m_longPressTimer->stop();
       
  1257             delete m_longPressTimer;
       
  1258             m_longPressTimer = 0;
       
  1259         }
       
  1260 }
       
  1261 void GWebTouchNavigation::getFocusedElement()
       
  1262 {
       
  1263 	QWebHitTestResult htRes = m_frame->hitTestContent(m_touchPosition);
       
  1264 	wrtBrowserDefs::BrowserElementType elType = wrtBrowserUtils::getTypeFromElement(htRes);
       
  1265 	emit focusElementChanged(elType);
       
  1266 }
       
  1267 
       
  1268 void GWebTouchNavigation::scrollCurrentFrame (int dx, int dy)
       
  1269 {
       
  1270    QPoint scrollPosition = m_frame->scrollPosition();
       
  1271    if (m_frame == m_webPage->mainFrame() && 
       
  1272         //scrollPosition.y() < m_chrome->getSnippetRect("UrlSearchChromeId").height()) {
       
  1273         scrollPosition.y() <=0  &&
       
  1274         !m_isLoading &&
       
  1275         !m_view->view()->currentPageIsSuperPage()) {
       
  1276     	  qreal slide = m_chrome->slideView(-dy);
       
  1277     	  dy+=slide;
       
  1278     }
       
  1279     
       
  1280     m_frame->scroll(dx, dy);
       
  1281 }
       
  1282 
       
  1283 void GWebTouchNavigation::setCurrentFrameScrollPosition (QPoint& pos)
       
  1284 {
       
  1285     QPoint scrollPosition = m_frame->scrollPosition();
       
  1286     QPoint finalPos = pos;
       
  1287     
       
  1288     
       
  1289     /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/
       
  1290     if (m_frame == m_webPage->mainFrame() && 
       
  1291         //scrollPosition.y() < m_chrome->getSnippetRect("UrlSearchChromeId").height()) {
       
  1292         scrollPosition.y() <=0 &&
       
  1293         !m_isLoading &&
       
  1294         !m_view->view()->currentPageIsSuperPage()) {
       
  1295         	
       
  1296     	  int dy = scrollPosition.y() - pos.y();
       
  1297     	  qreal slide = m_chrome->slideView(-dy);
       
  1298     	  dy+=slide;
       
  1299     	  finalPos.setY(scrollPosition.y() - dy);
       
  1300     }
       
  1301     	
       
  1302     m_frame->setScrollPosition(finalPos);
       
  1303 }
       
  1304 
       
  1305 void GWebTouchNavigation::onLoadStarted()
       
  1306 { 
       
  1307   	m_isLoading = true; 
       
  1308 }
       
  1309 void GWebTouchNavigation::onLoadFinished(bool ok)
       
  1310 {
       
  1311 	  m_isLoading = false;
       
  1312 }
       
  1313 void GWebTouchNavigation::setPage( QWebPage * page)
       
  1314 { 
       
  1315 	  disconnect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted()));
       
  1316     disconnect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool)));
       
  1317 	  m_webPage = page ;
       
  1318 	  connect(m_webPage, SIGNAL(loadStarted()), this, SLOT(onLoadStarted()));
       
  1319     connect(m_webPage, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool)));
       
  1320 }
       
  1321 }