diff -r bf4420e9fa4d -r 2e16851ffecd browsercore/core/webtouchnavigation.cpp --- a/browsercore/core/webtouchnavigation.cpp Fri Jun 11 16:23:26 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1288 +0,0 @@ -/* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* -*/ - - -#include "webtouchnavigation.h" -#include "qwebpage.h" -#include "qwebframe.h" -#include "qapplication.h" -#include "qwebelement.h" -#include -#include -#include - -#include "webcontentview.h" -#include "wrtBrowserUtils.h" - - -#define LONG_PRESS_DURATION 500 - -const int KFlickSpeed = 400; -const qreal PI = 3.1415926535897932; -const qreal KAngleTolerance = 30; -const int KAnimationTimeout = 40; -const qreal KDecelerationFactor = 0.8; -const int KMilliSecond = 1000; -const int KThresholdForRightToLeftMotion = 100; // 100 pixels -const int KThresholdForLeftToRightMotion = -100; // 100 pixels -const int XAlignVal = 10; -const int KDecelerationTimer = 125; //Decelerate only if flicked/swiped after KDecelerationTimer milli seconds after last drag event -const int KDoubleClickTimeOut = 400; -const QPoint KFocussPoint(5, 50); -const int KTouchThresholdX = 20; -const int KTouchThresholdY = 20; -const int KThreshHoldValForLink = 10; -const qreal KDeccelaration = 1000.00; -const int KDefaultViewportWidth = 980; -const int KDefaultPortraitScaleWidth = 540; - -const int KKineticTimeout = 60; -const int KMinBlockWidth = 50; - -static const int KStartPanDistance = 50; -static const int KWaitForClickTimeoutMS = 200; -//The amount of pixels to try to pan before pan mode unlocks -static const int KPanModeChangeDelta = 100; - -namespace WRT { - -/*! - \class WebTouchNavigation - \since cwrt 1.0 - \brief cwrt navigation. - - \sa WebNavigation, WebHtmlTabIndexedNavigation, WebCursorNavigation, WebDirectionalNavigation -*/ -WebTouchNavigation::WebTouchNavigation(QWebPage* webPage,QObject* view) -: m_webPage(webPage) -, m_view(view) -, m_frame(0) -, m_scrollTimer(0) -, m_doubleClickTimer(0) -, m_pressEvent(0) -, m_releaseEvent(0) -, m_focusedBlockPt(-1, -1) -, m_ishighlighted(false) -, m_offset(0) -, m_longPressTimer(0) -, m_finalzoomfactor(0) -, m_kineticTimer(0) -, m_isPanning(false) -{ - install(); - WebContentWidget* currentView = qobject_cast(m_view); - connect(currentView, SIGNAL(BlockFocusChanged(QPoint)), this, SLOT(BlockFocusChanged(QPoint))); -} - -/*! -*/ -WebTouchNavigation::~WebTouchNavigation() -{ - disconnect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired())); - if (m_doubleClickTimer) { - m_doubleClickTimer->stop(); - delete m_doubleClickTimer; - } - disconnect(m_scrollTimer, SIGNAL(timeout()),this,SLOT(pan())); - delete m_scrollTimer; - - disconnect(m_kineticTimer, SIGNAL(timeout()),this,SLOT(kineticScroll())); - delete m_kineticTimer; - uninstall(); -} - -void WebTouchNavigation::install() -{ - m_view->installEventFilter(this); -} - -void WebTouchNavigation::BlockFocusChanged(QPoint pt) -{ - m_focusedBlockPt = pt; -} - -void WebTouchNavigation::uninstall() -{ - if (m_view) - m_view->removeEventFilter(this); -} - -bool WebTouchNavigation::eventFilter(QObject *object, QEvent *event) -{ - bool ret = false; - if (object != m_view) - return false; - -{ - switch (event->type()) { - case QEvent::MouseButtonPress: - if (static_cast(event)->buttons() & Qt::LeftButton) { - mousePressEvent(static_cast(event)->pos()); - return true; - } - break; - case QEvent::MouseMove: - if (static_cast(event)->buttons() & Qt::LeftButton) { - mouseMoveEvent(static_cast(event)->pos()); - return true; - } - break; - case QEvent::MouseButtonRelease: - mouseReleaseEvent(static_cast(event)->pos()); - return true; - case QEvent::MouseButtonDblClick: - mouseDoubleClickEvent(static_cast(event)->pos()); - return true; - case QEvent::GraphicsSceneMousePress: - if (static_cast(event)->buttons() & Qt::LeftButton) { - mousePressEvent(static_cast(event)->pos().toPoint()); - return true; - } - break; - case QEvent::GraphicsSceneMouseMove: - if (static_cast(event)->buttons() & Qt::LeftButton) { - mouseMoveEvent(static_cast(event)->pos().toPoint()); - return true; - } - break; - case QEvent::GraphicsSceneMouseRelease: { - mouseReleaseEvent(static_cast(event)->pos().toPoint()); - return true; - } - break; - case QEvent::GraphicsSceneMouseDoubleClick: - mouseDoubleClickEvent(static_cast(event)->pos().toPoint()); - return true; - break; - default: - break; - } - } - return false; -} - -void WebTouchNavigation::stopScrolling() -{ - if (m_scrollTimer && m_scrollTimer->isActive()) { - m_scrollTimer->stop(); - m_scrollDelta = QPoint(0,0); - } - - if (m_kineticTimer && m_kineticTimer->isActive()) { - m_kineticTimer->stop(); - m_kineticSpeed.setX(0.0); - m_kineticSpeed.setY(0.0); - } -} - - -void WebTouchNavigation::pan() -{ - if (m_scrollDelta.x() != 0 || m_scrollDelta.y() != 0) { - scrollCurrentFrame(-m_scrollDelta.x(), m_scrollDelta.y()); - m_scrollDelta = QPoint(0,0); - } -} - -#define DECELERATION 0.0002 - -void WebTouchNavigation::kineticScroll() -{ - qreal decelX = m_kineticSpeed.x() > 0 ? -DECELERATION : DECELERATION; - qreal decelY = m_kineticSpeed.y() > 0 ? -DECELERATION : DECELERATION; - qreal dx = 0; - qreal dy = 0; - qreal vx = 0; - qreal vy = 0; - - m_kineticScrollTime += m_actualTime.elapsed(); - - if (m_kineticSpeed.x()) { - vx = m_kineticSpeed.x() + decelX * m_kineticScrollTime; - if (vx * m_kineticSpeed.x() < 0) { - dx = 0; - vx = 0; - } - else { - dx = m_kineticScrollTime * m_kineticSpeed.x() + - 0.5 * decelX * m_kineticScrollTime * m_kineticScrollTime; - } - } - - if (m_kineticSpeed.y()) { - vy = m_kineticSpeed.y() + decelY * m_kineticScrollTime; - if (vy * m_kineticSpeed.y() < 0) { - dy = 0; - vy = 0; - } - else { - dy = m_kineticScrollTime * m_kineticSpeed.y() + - 0.5 * decelY * m_kineticScrollTime * m_kineticScrollTime; - } - } - - QPoint scrollPos = m_frame->scrollPosition(); - QPoint distPos = m_initialScrollPos + QPointF(dx, dy).toPoint(); - - - - if (vx != 0 || vy != 0) { - setCurrentFrameScrollPosition(distPos); - } - - if ((vx == 0 && vy == 0) || scrollPos == m_frame->scrollPosition()) { - stopScrolling(); - } - -} - - - -/*! - Scrolls QWebFrame to the given position - \sa QWebFrame::scroll() -*/ -void WebTouchNavigation::scrollFrame(const QPoint& pos) -{ - if (m_touchPosition != pos) { - QPoint diff = m_touchPosition-pos; - if (qAbs(diff.x()) < 10 && qAbs(diff.y()) < 10) - return; - else if(m_dragPoints.size() == 1) { - WebContentWidget* view = qobject_cast(m_view); - view->setBlockElement(QWebElement()); - } - - if(!m_isPanning) { - qreal dy = qAbs(diff.y()); - qreal dx = qAbs(diff.x()); - if (dy > KStartPanDistance || dx > KStartPanDistance - || m_delayedPressMoment.elapsed() > KWaitForClickTimeoutMS) { - //get the scroll direction - Direction scrollDir = findDirectionWithAngle(m_touchPosition,pos); - if(scrollDir == UP || scrollDir == DOWN) - startPanGesture(VerticalPan); - else if(scrollDir == LEFT || scrollDir == RIGHT) - startPanGesture(HorizontalPan); - else - startPanGesture(RandomPan); - m_isPanning = true; - m_dragStartPos = pos; - } - } - - if (m_isPanning) { - m_scrolled= false; - m_frame = getNextScrollableFrame(diff); - QPoint scrollPosition = m_frame->scrollPosition(); - if (diff.manhattanLength()) - panBy(diff); - - m_scrolled = (scrollPosition != m_frame->scrollPosition()); - m_dragStartPos = pos; - } - - m_touchPosition = pos; - DragPoint dragPoint; - dragPoint.iPoint = pos; - dragPoint.iTime = QTime::currentTime(); - m_dragPoints.append(dragPoint); - - QTime now(QTime::currentTime()); - m_lastMoveEventTime.setHMS(now.hour(),now.minute(), now.second(), now.msec()); - - while (m_dragPoints.size() > 4) - m_dragPoints.removeFirst(); - } -} - -void WebTouchNavigation::startPanGesture(PanDirection directionHint) { - m_panDirection = directionHint; - m_panModeResidue = QPointF(0., 0.); -} -void WebTouchNavigation::panBy(const QPointF& delta) { - - m_panModeResidue += delta; - - if (qAbs(m_panModeResidue.x()) > KPanModeChangeDelta) - m_panDirection = HorizontalPan; - - if (qAbs(m_panModeResidue.y()) > KPanModeChangeDelta) - m_panDirection = VerticalPan; - - if(qAbs(m_panModeResidue.x()) > KPanModeChangeDelta - && qAbs(m_panModeResidue.y()) > KPanModeChangeDelta) - m_panDirection = RandomPan; - - QPointF p; - if(m_panDirection == HorizontalPan) - p.setX(delta.x()); - if(m_panDirection == VerticalPan) - p.setY(delta.y()); - if(m_panDirection == RandomPan) { - p.setX(delta.x()); - p.setY(delta.y()); - } - - scrollCurrentFrame(p.x(),p.y()); -} - -void WebTouchNavigation::highlightableElement(QMouseEvent* ev) { - m_anchorElement = getClosestAnchorElement(ev); -} - -inline int xInRect(const QRect& r, int x) -{ - return std::min(std::max(x, r.x()), r.x() + r.width()); -} - -inline int yInRect(const QRect& r, int y) -{ - return std::min(std::max(y, r.y()), r.y() + r.height()); -} - -bool WebTouchNavigation::traverseNextNode(QWebElement parentNode,QWebElement& nextNode) -{ - if (!parentNode.firstChild().isNull()) { - nextNode = parentNode.firstChild(); - return true; - } - - if (!parentNode.nextSibling().isNull()) { - nextNode = parentNode.nextSibling(); - return true; - } - - QWebElement n = parentNode; - while (!n.isNull() && n.nextSibling().isNull()) - n = n.parent (); - - if (!n.isNull()) { - nextNode = n.nextSibling(); - return true; - } - - return false; -} - - -QWebElement WebTouchNavigation::getClosestAnchorElement(QMouseEvent* ev) -{ - QWebElement webElement; - QWebHitTestResult htRes = getHitTestResult(ev); - QWebElement hitElement = htRes.element(); - //check whether hit test returns a link element - if(!htRes.linkElement().isNull()) { - webElement = htRes.linkElement(); - m_higlightedPos = ev->pos(); - m_ishighlighted = true; - } - //get the closet anchor element - else { - QPoint docPoint = (m_touchPosition + m_frame->scrollPosition()); - int dist = 99999999; - QWebElement result; - QWebElement ele = m_webPage->currentFrame()->documentElement(); - do { - if(ele.tagName().compare("a",Qt::CaseInsensitive) == 0 ) { - QRect r = ele.geometry(); - if(r.contains(docPoint)) { - dist = 0; - result = ele; - break; - } - - int x = xInRect(r, docPoint.x()); - int y = yInRect(r, docPoint.y()); - int d = (docPoint.x() - x) * (docPoint.x() - x) + (docPoint.y() - y) * (docPoint.y() - y); - if (dist > d) { - dist = d; - result = ele; - } - } - }while(traverseNextNode(ele,ele)); - - WebContentWidget* view = qobject_cast(m_view); - // check if we are close enough and calcualte with zoom factor. - if (dist< (KThreshHoldValForLink/view->zoomFactor())) { - QRect r = result.geometry(); - r.translate(2,2); - r.setWidth(2+2); - r.setHeight(2+2); - webElement = result; - m_higlightedPos = QPoint(xInRect(r, docPoint.x()), yInRect(r, docPoint.y())) - m_frame->scrollPosition(); - m_ishighlighted = true; - QPoint centerpt = webElement.geometry().center(); - m_offset = (docPoint.x()- centerpt.x())*(docPoint.x()- centerpt.x()) + (docPoint.y()- centerpt.y())*(docPoint.y()- centerpt.y()); - - } - } - return webElement; -} - -/*! - Sends a mouse press event to QWebPage -*/ -void WebTouchNavigation::mousePressEvent(const QPoint& pos) -{ - m_delayedPressMoment.start(); - // stop deceleration and don't send further events to engine if scroll timer is active - if(m_scrollTimer && m_scrollTimer->isActive()) { - m_prevPoint.setX(0); - m_prevPoint.setY(0); - m_scrollDistance.setX(0); - m_scrollDistance.setY(0); - - m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS - m_scrolled = false; - m_ishighlighted = false; - m_higlightedPos = m_touchPosition = pos; - m_frame = m_webPage->frameAt(pos); - if (!m_frame) - m_frame = m_webPage->currentFrame(); - - m_dragPoints.clear(); - - DragPoint dragPoint; - dragPoint.iPoint = m_touchPosition; - dragPoint.iTime = QTime::currentTime(); - m_dragPoints.append(dragPoint); - m_offset = 0; - - m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, m_touchPosition, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - m_scrollTimer->stop(); - return; - } - - if (m_doubleClickTimer) { - // If there is another click event almost on the same region - // as the previous click before doubleClick timeout - // Consider it as double click. - if (m_doubleClickTimer->isActive() && m_pressEvent) { - QPoint diff = m_pressEvent->pos() - pos; - if (qAbs(diff.x()) < KTouchThresholdX && qAbs(diff.y()) < KTouchThresholdY) { - mouseDoubleClickEvent(pos); - return; - } - } - m_doubleClickTimer->stop(); - } else { - m_doubleClickTimer = new QTimer(this); - connect(m_doubleClickTimer, SIGNAL(timeout()), this, SLOT(doubleClickTimerExpired())); - } - - //Clear the previous press and release events. - if (m_pressEvent) { - delete m_pressEvent; - m_pressEvent = NULL; - } - - if (m_releaseEvent) { - delete m_releaseEvent; - m_releaseEvent = NULL; - } - - m_doubleClickTimer->start(KDoubleClickTimeOut); - m_pressEvent = new QMouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); -} - -void WebTouchNavigation::handleMousePressEvent(QMouseEvent* ev) -{ - m_lastMoveEventTime.setHMS(0,0,0,0); //H, M, S, mS - if(!m_longPressTimer){ - delete m_longPressTimer; - m_longPressTimer = 0; - } - startTimer(); - m_scrolled = false; - m_ishighlighted = false; - m_higlightedPos = m_touchPosition = ev->pos(); - m_frame = m_webPage->frameAt(ev->pos()); - if (!m_frame) - m_frame = m_webPage->currentFrame(); - - m_dragPoints.clear(); - - DragPoint dragPoint; - dragPoint.iPoint = m_touchPosition; - dragPoint.iTime = QTime::currentTime(); - m_dragPoints.append(dragPoint); - - m_offset = 0; - - highlightableElement(ev); - getFocusedElement(); - - //send a mouse press - QMouseEvent iev(ev->type(), m_touchPosition, ev->button(), ev->buttons(), ev->modifiers()); - m_webPage->event(&iev); -} - -void WebTouchNavigation::doubleClickTimerExpired() -{ - handleMousePressEvent(m_pressEvent); - - delete m_pressEvent; - m_pressEvent = NULL; - - if (m_releaseEvent) { - handleMouseReleaseEvent(m_releaseEvent); - - //clear release event - delete m_releaseEvent; - m_releaseEvent = NULL; - } - if (m_doubleClickTimer && m_doubleClickTimer->isActive()) - m_doubleClickTimer->stop(); -} - -bool WebTouchNavigation::canDehighlight(QMouseEvent* ev) - { - bool checkDehighlight = false; - QPoint pt = ev->pos() + m_frame->scrollPosition(); - - if(m_scrolled && m_ishighlighted) { - checkDehighlight = true; - } - else if(!m_scrolled && m_ishighlighted) { - QRect rect = m_anchorElement.geometry(); - - if(m_anchorElement.geometry().contains(pt)) { - checkDehighlight = false; - } - else if(m_offset){ - QPoint centerpt = m_anchorElement.geometry().center(); - int newoffset = (pt.x()- centerpt.x())*(pt.x()- centerpt.x()) + (pt.y()- centerpt.y())*(pt.y()- centerpt.y()); - - if(newoffset <= m_offset ) { - m_offset = newoffset; - checkDehighlight = false; - } - else { - m_offset =0; - checkDehighlight = true; - } - } - else { - checkDehighlight = true; - } - } - return checkDehighlight; -} - void WebTouchNavigation::dehighlight(QMouseEvent* ev) -{ - m_higlightedPos = QPoint(0,0); - m_ishighlighted = false; - QMouseEvent iev(QEvent::MouseButtonPress,m_higlightedPos,ev->button(), ev->buttons(), ev->modifiers()); - m_webPage->event(&iev); -} - -void WebTouchNavigation::handleHighlightChange(QMouseEvent* ev) -{ - if (!canDehighlight(ev)) return; - - dehighlight(ev); -} - -/*! - Scrolls the frame - \sa scrollFrame() -*/ -void WebTouchNavigation::mouseMoveEvent(const QPoint& pos) -{ - if (m_pressEvent) { - QPoint diff = m_pressEvent->pos() - pos; - if (qAbs(diff.x()) < KTouchThresholdX && qAbs(diff.y()) < KTouchThresholdY) - return; - } - - if (m_doubleClickTimer && m_doubleClickTimer->isActive()) { - //send mousePressEvent - m_doubleClickTimer->stop(); - handleMousePressEvent(m_pressEvent); - delete m_pressEvent; - m_pressEvent = NULL; - } - - stopTimer(); - QMouseEvent tmpEv(QEvent::MouseMove, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - handleHighlightChange(&tmpEv); - - scrollFrame(pos); -} - -/*! - If WebCanvas or QWebFrame were scrolled starts the deceleration alogrithm - Otherwise sends the mouse release event to QWebPage - \sa startDeceleration() -*/ -void WebTouchNavigation::mouseReleaseEvent(const QPoint& pos) -{ - if(m_isPanning) - m_isPanning = false; - if (m_doubleClickTimer && m_doubleClickTimer->isActive()) { - m_releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - return; - } - //mouseReleaseEvent is called in two cases. 1. Double click, 2. Mouse Drag - //m_releaseEvent is not null only in Mouse double click - //So delete m_releaseEvent only in double click case. - //Send release event in mouse move case - if (m_releaseEvent) { - delete m_releaseEvent ; - m_releaseEvent = NULL; - } else { - QMouseEvent tmpEv(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - handleMouseReleaseEvent(&tmpEv); - } -} - -void WebTouchNavigation::handleMouseReleaseEvent(QMouseEvent* ev) -{ - m_frame = m_webPage->frameAt(ev->pos()); - if (!m_frame) - m_frame = m_webPage->currentFrame(); - assert(m_frame); - - stopTimer(); - if (m_scrolled) { - int msecs = 0; - if (!m_lastMoveEventTime.isNull()) { - //Start deceleration only if the delta since last drag event is less than threshold - QTime now(QTime::currentTime()); - msecs = m_lastMoveEventTime.msecsTo(now); - m_lastMoveEventTime.setHMS(0,0,0,0); - } - if (msecs < KDecelerationTimer) { - if( isFlick()) { - updateFlickScrollDistance(); - } - else { - QRect enclosingRect = findEnclosingBlock(ev); - QPoint blockDocPt(enclosingRect.x(), enclosingRect.y()); - QPoint blockCanvasPoint(blockDocPt - m_frame->scrollPosition()); - calculateActualScrollDistance(); - int thresholdCheckVal = blockCanvasPoint.x() - m_actualScrollDistance.x(); - setNewScrollDistance(blockCanvasPoint, thresholdCheckVal); - } - startScrollTimer(); - } - } else { - Qt::KeyboardModifier modifier = Qt::NoModifier; - QWebHitTestResult htr = m_frame->hitTestContent(ev->pos()); - if (htr.element().tagName().toLower().compare("select")==0 && htr.element().hasAttribute("multiple")) - modifier = Qt::ControlModifier; - - //send a mouse press - if(m_ishighlighted) { - QMouseEvent iev(ev->type(), m_higlightedPos, ev->button(), ev->buttons(), ev->modifiers()); - m_webPage->event(&iev); - } - else { - QMouseEvent ievr(QEvent::MouseButtonRelease, m_touchPosition, ev->button(), ev->buttons(), modifier); - m_webPage->event(&ievr); - } -#if defined CWRTINTERNALWEBKIT && __SYMBIAN32__ -// FIXME Remove this, it is fixed Qt 4.6 - if (ev->button() == Qt::LeftButton) { - QWebHitTestResult htr = m_frame->hitTestContent(ev->pos()); - if (htr.isContentEditable()) { - QEvent vkbEvent(QEvent::RequestSoftwareInputPanel); - QApplication::sendEvent(m_view, &vkbEvent); - } - } -#endif - } -} - -void WebTouchNavigation::mouseDoubleClickEvent(const QPoint& pos) -{ - - if(m_doubleClickTimer && !m_doubleClickTimer->isActive()) - return; - else if(m_doubleClickTimer) - m_doubleClickTimer->stop(); - - //If the page is already scrolling(because of a previous doubletap) - //we need to stop the timer before we start scrolling the new block again. - if (m_scrollTimer && m_scrollTimer->isActive()) - m_scrollTimer->stop(); - - QMouseEvent tmpEv(QEvent::MouseButtonDblClick, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - handleDoubleClickEvent(&tmpEv); -} - -void WebTouchNavigation::handleDoubleClickEvent(QMouseEvent* ev) -{ - QPoint imageFocusPoint; - QWebHitTestResult hitTest = getHitTestResult(ev); - - QWebElement block = hitTest.element(); - - if (block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) - block = hitTest.enclosingBlockElement(); - - while (!block.isNull() && block.geometry().width() < KMinBlockWidth) { - block = block.parent(); - } - if(block.isNull()) - return; - - QWebFrame* frame = m_webPage->frameAt(ev->pos()); - m_frame = (frame) ? frame : m_webPage->mainFrame(); - - QRect enclosingRect = block.geometry(); - - QPoint blockCanvasPt = QPoint(enclosingRect.topLeft()) - m_frame->scrollPosition(); - WebContentWidget* view = qobject_cast(m_view); - view->setBlockElement(QWebElement()); - if(m_focusedBlockPt == blockCanvasPt) { - m_focusedBlockPt.setX(-1); - m_focusedBlockPt.setY(-1); - qreal m_Ratiox = (qreal) blockCanvasPt.x() / block.geometry().width(); - qreal m_Ratioy = (qreal) blockCanvasPt.y() / block.geometry().height(); - view->setZoomFactor(view->initialScale()); - QPoint m_InfocusBlockPt = QPoint(block.geometry().topLeft()) - m_webPage->mainFrame()->scrollPosition(); - m_webPage->currentFrame()->scroll(m_InfocusBlockPt.x() - (m_Ratiox * block.geometry().width()), - m_InfocusBlockPt.y() - (m_Ratioy * block.geometry().height())); - m_finalzoomfactor = 0; - }else { - if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) { - m_finalzoomfactor = (qreal) (m_webPage->viewportSize().width() - 10) * view->zoomFactor(); - m_finalzoomfactor = (qreal) m_finalzoomfactor / (enclosingRect.width()); - QString str; - str.setNum(m_finalzoomfactor,'f',2); - m_finalzoomfactor = str.toDouble(); - }else { - qreal factor; - factor = 1/view->initialScale(); - int boundW = block.geometry().width() * factor/view->zoomFactor(); - int boundH = block.geometry().height() * factor/view->zoomFactor(); - qreal factorw = 0.0,factorh = 0.0 ; - - if( boundW > m_webPage->viewportSize().width()) - factorw = (qreal)(m_webPage->viewportSize().width()-5)/ block.geometry().width(); - - if(boundH > m_webPage->viewportSize().height()) - factorh = (qreal)(m_webPage->viewportSize().height()-5)/ block.geometry().height(); - - if( (factorw == 0.0) && (factorh == 0.0)) - ; - else if(factorw == 0.0) - factor = factorh * view->zoomFactor(); - else if(factorh == 0.0) - factor = factorw * view->zoomFactor(); - else { - factor = ((factorh < factorw) ? factorh : factorw) * view->zoomFactor(); - } - - QString str; - str.setNum(factor,'f',2); - factor = str.toDouble(); - - if(m_finalzoomfactor != factor) - m_finalzoomfactor = factor; - } - - - if (m_finalzoomfactor != view->zoomFactor()) { - view->setZoomFactor(m_finalzoomfactor); - m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition(); - - if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) - scrollCurrentFrame(m_focusedBlockPt.x() - KFocussPoint.x() , m_focusedBlockPt.y() - KFocussPoint.y()); - else { - if((m_webPage->viewportSize().width() - block.geometry().width()) > 0) - imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2); - else - imageFocusPoint.setX(0); - - if((m_webPage->viewportSize().height() - block.geometry().height()) > 0) - imageFocusPoint.setY((m_webPage->viewportSize().height() - block.geometry().height())/2); - else - imageFocusPoint.setY(0); - - scrollCurrentFrame(m_focusedBlockPt.x() - imageFocusPoint.x() , m_focusedBlockPt.y() - imageFocusPoint.y()); - } - - m_focusedBlockPt = QPoint(block.geometry().topLeft()) - m_frame->scrollPosition(); - } else { - //Get doc size and current bottom right view corner point in document - QSize viewSize = m_webPage->viewportSize(); - QSize contentSize = m_frame->contentsSize(); - QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition(); - QPoint docFocusPoint; - - if(block.tagName() != "IMG" && (block.styleProperty(QString("background-image"),QWebElement::InlineStyle) == "")) - docFocusPoint = KFocussPoint + m_frame->scrollPosition(); - else { - if((m_webPage->viewportSize().width() - block.geometry().width()) > 0) - imageFocusPoint.setX((m_webPage->viewportSize().width() - block.geometry().width())/2); - else - imageFocusPoint.setX(0); - - if((m_webPage->viewportSize().height() - block.geometry().height()) > 0) - imageFocusPoint.setY((m_webPage->viewportSize().height()- block.geometry().height())/2); - else - imageFocusPoint.setY(0); - - docFocusPoint = imageFocusPoint + m_frame->scrollPosition(); - } - - m_focusedBlockPt = QPoint(block.geometry().x(), block.geometry().y()); - m_scrollDistance.setX(m_focusedBlockPt.x() - docFocusPoint.x()); - m_scrollDistance.setY(m_focusedBlockPt.y() - docFocusPoint.y()); - - QPoint scrollableDistance(0, 0); - QPoint viewStartPoint = QPoint(0,0) + m_frame->scrollPosition(); - - if(m_scrollDistance.x() < 0) - scrollableDistance.setX(viewStartPoint.x()); - else - scrollableDistance.setX(contentSize.width() - documentViewPoint.x()); - - - if(m_scrollDistance.y() < 0) - scrollableDistance.setY(viewStartPoint.y()); - else - scrollableDistance.setY(contentSize.height() - documentViewPoint.y()); - - if(abs(m_scrollDistance.x()) > abs(scrollableDistance.x())){ - //m_scrollDistance.x() >= 0 means scroll from right to left - if(m_scrollDistance.x() >= 0) - m_focusedBlockPt.setX(m_focusedBlockPt.x() - abs(scrollableDistance.x())); - //m_scrollDistance.x() < 0 means scroll from left to right - else - m_focusedBlockPt.setX(m_focusedBlockPt.x() + abs(scrollableDistance.x())); - } else - m_focusedBlockPt.setX(docFocusPoint.x()); - - if (abs(m_scrollDistance.y()) > abs(scrollableDistance.y())){ - if(m_scrollDistance.y() >= 0) - m_focusedBlockPt.setY(m_focusedBlockPt.y() - abs(scrollableDistance.y())); - else - m_focusedBlockPt.setY(m_focusedBlockPt.y() + abs(scrollableDistance.y())); - } - else - m_focusedBlockPt.setY(docFocusPoint.y()); - - m_focusedBlockPt = m_focusedBlockPt - m_frame->scrollPosition(); - startScrollTimer(); - } - view->setBlockElement(block); - } -} - -/*! - Returns the next scrollable frame in the frame tree give the x,y position -*/ -QWebFrame* WebTouchNavigation::getNextScrollableFrame(const QPoint& pos) -{ - QWebFrame* frame = m_frame; - while (frame) { - if (pos.x() > 0) { - if (frame->scrollBarValue(Qt::Horizontal) < frame->scrollBarMaximum(Qt::Horizontal)) - break; - } - else if (pos.x() < 0) { - if (frame->scrollBarValue(Qt::Horizontal) > frame->scrollBarMinimum(Qt::Horizontal)) - break; - } - - if (pos.y() > 0) { - if (frame->scrollBarValue(Qt::Vertical) < frame->scrollBarMaximum(Qt::Vertical)) - break; - } - else if (pos.y() < 0) { - if (frame->scrollBarValue(Qt::Vertical) > frame->scrollBarMinimum(Qt::Vertical)) - break; - } - frame = frame->parentFrame(); - } - return (frame)?frame:m_webPage->mainFrame(); -} - -/* -Starts the timer for scrolling smoothly to the destination location . -The timer will do the decelaration while scrolling -*/ -void WebTouchNavigation::startScrollTimer() -{ - if(!m_scrollTimer) { - m_scrollTimer = new QTimer(this); - connect(m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollToEdge())); - } - m_scrollTimer->stop(); - m_scrollTimer->start(KAnimationTimeout); -} - -/* -Update the scroll distance for flick gesture. Update the scroll distance upto the edge of the page -*/ -void WebTouchNavigation::updateFlickScrollDistance() -{ - m_initialSpeed = speed(); - m_initialSpeed.setX(qAbs(m_initialSpeed.x())); - m_initialSpeed.setY(qAbs(m_initialSpeed.y())); - m_flickDirection = findDirectionWithAngle(m_dragPoints.first().iPoint,m_dragPoints.last().iPoint); - m_scrollDistance.setX((m_initialSpeed.x() * m_initialSpeed.x())/( 2 * KDeccelaration)); - m_scrollDistance.setY((m_initialSpeed.y() * m_initialSpeed.y())/( 2 * KDeccelaration)); - - WebContentWidget* view = qobject_cast(m_view); - m_scrollDistance.setX(view->zoomFactor() * m_scrollDistance.x() / view->initialScale()); - m_scrollDistance.setY(view->zoomFactor() * m_scrollDistance.y() / view->initialScale()); - - QSize viewSize = m_webPage->viewportSize(); - QSize contentSize = m_frame->contentsSize(); - QPoint documentViewPoint = QPoint(viewSize.width(),viewSize.height()) + m_frame->scrollPosition(); - QPoint documentTouchPoint = m_touchPosition + m_frame->scrollPosition();; - - switch(m_flickDirection) - { - case DOWN : - m_scrollDistance.setX(0); - m_scrollDistance.setY(-(m_scrollDistance.y())); - - if(m_scrollDistance.y() < -(documentTouchPoint.y() - m_touchPosition.y())) - m_scrollDistance.setY(-(documentTouchPoint.y() - m_touchPosition.y())); - break; - case UP : - m_scrollDistance.setX(0); - if(m_scrollDistance.y() > (contentSize.height() - documentViewPoint.y())) - m_scrollDistance.setY(contentSize.height() - documentViewPoint.y()); - break; - case RIGHT: - m_scrollDistance.setX(-(m_scrollDistance.x())); - if(m_scrollDistance.x() < -(documentTouchPoint.x() - m_touchPosition.x())) - m_scrollDistance.setX(-(documentTouchPoint.x() - m_touchPosition.x())); - m_scrollDistance.setY(0); - break; - case LEFT: - m_scrollDistance.setY(0); - if(m_scrollDistance.x() > (contentSize.width() - documentViewPoint.x())) - m_scrollDistance.setX(contentSize.width() - documentViewPoint.x()); - break; - case BOTTOMRIGHT: - m_scrollDistance.setX(-(m_scrollDistance.x())); - m_scrollDistance.setY(-(m_scrollDistance.y())); - if(m_scrollDistance.x() < -(documentTouchPoint.x()-m_touchPosition.x())) - m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x())); - if(m_scrollDistance.y() < -((documentTouchPoint.y()-m_touchPosition.y())/2)) - m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2)); - break; - case BOTTOMLEFT: - m_scrollDistance.setY(-(m_scrollDistance.y())); - if(m_scrollDistance.x() > contentSize.width()-documentViewPoint.x()) - m_scrollDistance.setX(contentSize.width()-documentViewPoint.x()); - if(m_scrollDistance.y() < (-((documentTouchPoint.y()-m_touchPosition.y())/2))) - m_scrollDistance.setY(-((documentTouchPoint.y()-m_touchPosition.y())/2)); - break; - case TOPLEFT: - if(m_scrollDistance.x() > (contentSize.width()-documentViewPoint.x())) - m_scrollDistance.setX(contentSize.width()-documentViewPoint.x()); - if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2)) - m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2); - break; - case TOPRIGHT: - m_scrollDistance.setX(-(m_scrollDistance.x())); - if(m_scrollDistance.x() < (-(documentTouchPoint.x()-m_touchPosition.x()))) - m_scrollDistance.setX(-(documentTouchPoint.x()-m_touchPosition.x())); - if(m_scrollDistance.y() > ((contentSize.height()-documentViewPoint.y())/2)) - m_scrollDistance.setY((contentSize.height()-documentViewPoint.y())/2); - break; - } -} - -/* -Distinguishes b/w swipe and flick -*/ -bool WebTouchNavigation::isFlick() -{ - bool flick = false; - QPoint moveSpeed = speed(); - int xSpeed = moveSpeed.x(); - int ySpeed = moveSpeed.y(); - - flick = (qAbs(xSpeed) > KFlickSpeed || - qAbs(ySpeed) > KFlickSpeed); - - return flick; -} - -/* -Calculates the speed of te scroll along x-axis and y-axis -*/ -QPoint WebTouchNavigation::speed() -{ - // Speed is only evaluated at the end of the swipe - QPoint dragSpeed(0,0); - qreal time = dragTime() / KMilliSecond; - if (time > 0) { - QPoint distance = currentPos() - previousPos(); - dragSpeed.setX((distance.x()) / time); - dragSpeed.setY((distance.y()) / time); - } - return dragSpeed; -} - -/* -Returns the last point in the m_dragPoints list -*/ -QPoint WebTouchNavigation::currentPos() -{ - return m_dragPoints[m_dragPoints.size()-1].iPoint; -} - -/* -Returns the first point in the m_dragPoints list -*/ -QPoint WebTouchNavigation::previousPos() -{ - return m_dragPoints[0].iPoint; -} - -/* -Finds the time difference b/w the first and last dragpoint -*/ -qreal WebTouchNavigation::dragTime() const -{ - if(m_dragPoints.isEmpty()) - return 0.0; - else - return m_dragPoints[0].iTime.msecsTo(m_dragPoints[m_dragPoints.size()-1].iTime); -} - -/*! -Find the flick direction with respect to angle of flick -*/ -Direction WebTouchNavigation::findDirectionWithAngle(const QPoint& stPoint,const QPoint& endPoint) -{ - Direction direction; - int xDelta = endPoint.x() - stPoint.x(); - int yDelta = endPoint.y() - stPoint.y(); - - qreal angle = findAngle(xDelta, yDelta); - if(isNear(angle, 60.0, 120.0)) { - direction = DOWN; - } - else if(isNear(angle, 150.0, 210.0)) { - direction = LEFT; - } - else if(isNear(angle, 240.0, 300.0)) { - direction = UP; - } - else if(360.0 - KAngleTolerance <= angle || angle <= KAngleTolerance) { - direction = RIGHT; - } - else if(isNear(angle, 30.0, 60.0)) { - direction = BOTTOMRIGHT; - } - else if(isNear(angle, 120.0, 150.0)) { - direction = BOTTOMLEFT; - } - else if(isNear(angle, 210.0, 240.0)) { - direction = TOPLEFT; - } - else if(isNear(angle, 300.0, 330.0)) { - direction = TOPRIGHT; - } - - return direction; -} - -/* -Check the angle is in the range of aMinAngle and aMaxAngle -*/ -bool WebTouchNavigation::isNear(qreal angleUnderTest, qreal minAngle, qreal maxAngle) -{ - return (minAngle < angleUnderTest) && (angleUnderTest <= maxAngle); -} - -/* -Find the angle from x and y displacement -*/ -qreal WebTouchNavigation::findAngle(const int& xDelta,const int& yDelta) -{ - qreal angle = 0; - qreal hypotenuse = qSqrt(xDelta*xDelta + yDelta*yDelta); - - if(hypotenuse != 0) { - angle = qAcos(xDelta / hypotenuse); - - if(yDelta < 0) { - angle = (2 * PI) - angle; - } - } - - return (angle * 180) / PI; -} - -int WebTouchNavigation::roundOff(qreal num) -{ - return (num + 0.5); -} - -/* -Finds out the enclosing block -*/ -QRect WebTouchNavigation::findEnclosingBlock(QMouseEvent* ev) -{ - QWebHitTestResult htr = getHitTestResult(ev); - QRect rect = htr.enclosingBlockElement().geometry(); - return rect; -} - -/* -Gets the hitTestResult for a particular event -*/ -QWebHitTestResult WebTouchNavigation::getHitTestResult(QMouseEvent* ev) -{ - QPoint pt = ev->pos(); - QWebFrame* frame = m_webPage->frameAt(pt); - frame = (frame) ? frame : m_webPage->mainFrame(); - QWebHitTestResult htr = frame->hitTestContent(pt); - return htr; -} - -/* -Finds out the scroll distance associated with a swipe -*/ -void WebTouchNavigation::calculateActualScrollDistance() -{ - m_actualScrollDistance.setX(0); - m_actualScrollDistance.setY(0); - if (!m_dragPoints.isEmpty()) { - QPoint distance = previousPos() - currentPos(); - if (qAbs(distance.x()) > 0 || qAbs(distance.y()) > 0) { - m_actualScrollDistance = distance / m_dragPoints.size() * 2; - } - } -} - -/* -In the case of slow swipe, if the destination location lies within the threshold area, then -we need to align the block to te left edge of the mobile screen. This method finds out the -new scroll distance -*/ -void WebTouchNavigation::setNewScrollDistance(QPoint blockCanvasPoint, int thresholdCheckVal) -{ - m_scrollDistance.setX(m_actualScrollDistance.x()); - m_scrollDistance.setY(m_actualScrollDistance.y()); - if(blockCanvasPoint.x() > 0) { - //Checks whether the block falls within the threshold after right to left swipe - if( (thresholdCheckVal < KThresholdForRightToLeftMotion) && (thresholdCheckVal > 0)) { - //if the block is within the threshold range already and the user tries - //to swipe from left to right , then let it move to right. Dont try to - //snap to the left edge . - if(m_actualScrollDistance.x() > 0) { - m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal); - } - } - } - else { - //Checks whether the block falls within the threshold after left to right swipe - if( (thresholdCheckVal > KThresholdForLeftToRightMotion) && (thresholdCheckVal < 0)) { - //if the block is within the threshold range already and the user tries - //to swipe from right to left , then let it move to left. Dont try to - //snap to the left edge . - if (m_actualScrollDistance.x() < 0) { - m_scrollDistance.setX(blockCanvasPoint.x() - XAlignVal); - } - } - - } -} - - -/* -SLOT associated with the timer to adjust the scroll to the edge -*/ -void WebTouchNavigation::scrollToEdge() -{ - m_prevPoint.setX(m_scrollDistance.x()); - m_prevPoint.setY(m_scrollDistance.y()); - - m_scrollDistance.setX(m_scrollDistance.x() * KDecelerationFactor); - m_scrollDistance.setY(m_scrollDistance.y() * KDecelerationFactor); - - //round off the values - m_scrollDistance.setX(roundOff(m_scrollDistance.x())); - m_scrollDistance.setY(roundOff(m_scrollDistance.y())); - - int diffX = m_prevPoint.x() - m_scrollDistance.x(); - int diffY = m_prevPoint.y() - m_scrollDistance.y(); - - if (((m_scrollDistance.x() == 0) && (m_scrollDistance.y() == 0)) - || ((diffX == 0) && (diffY == 0))) { - scrollCurrentFrame(m_prevPoint.x(), m_prevPoint.y()); - m_scrollTimer->stop(); - return; - } - scrollCurrentFrame(diffX, diffY); -} -void WebTouchNavigation::timerControl() -{ - stopTimer();// stop timer as soon as timeout - emit longPressEvent(); -} -void WebTouchNavigation::startTimer() -{ - m_longPressTimer = new QTimer(this); - connect(m_longPressTimer,SIGNAL(timeout()),this,SLOT(timerControl())); - m_longPressTimer->start(LONG_PRESS_DURATION); -} -void WebTouchNavigation::stopTimer() -{ - if(m_longPressTimer){ - m_longPressTimer->stop(); - delete m_longPressTimer; - m_longPressTimer = 0; - } -} -void WebTouchNavigation::getFocusedElement() -{ - QWebHitTestResult htRes = m_frame->hitTestContent(m_touchPosition); - wrtBrowserDefs::BrowserElementType elType = wrtBrowserUtils::getTypeFromElement(htRes); - emit focusElementChanged(elType); -} - -void WebTouchNavigation::scrollCurrentFrame (int dx, int dy) -{ - QPoint scrollPosition = m_frame->scrollPosition(); - m_frame->scroll(dx, dy); - - /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/ - if (m_frame == m_webPage->mainFrame()) { - if (scrollPosition.y() == 0 || m_frame->scrollPosition().y() == 0) { - emit pageScrollPositionZero(); - } - } -} - -void WebTouchNavigation::setCurrentFrameScrollPosition (QPoint& pos) -{ - QPoint scrollPosition = m_frame->scrollPosition(); - m_frame->setScrollPosition(pos); - - /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/ - if (m_frame == m_webPage->mainFrame()) { - if (scrollPosition.y() == 0 || m_frame->scrollPosition().y() == 0) { - emit pageScrollPositionZero(); - } - } -} -}