summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
commit49233e234e5c787396cadb2cea33b31ae0cd65c1 (patch)
tree5410cb9a8fd53168bb60d62c54b654d86f03c38d /Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp
parentb211c645d8ab690f713515dfdc84d80b11c27d2c (diff)
downloadqtwebkit-49233e234e5c787396cadb2cea33b31ae0cd65c1.tar.gz
Imported WebKit commit 3a8c29f35d00659d2ce7a0ccdfa8304f14e82327 (http://svn.webkit.org/repository/webkit/trunk@120813)
New snapshot with Windows build fixes
Diffstat (limited to 'Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp')
-rw-r--r--Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp752
1 files changed, 0 insertions, 752 deletions
diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp
deleted file mode 100644
index 053afff29..000000000
--- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp
+++ /dev/null
@@ -1,752 +0,0 @@
-/*
- * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this program; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "QtViewportInteractionEngine.h"
-
-#include "WebPageGroup.h"
-#include "WebPageProxy.h"
-#include "WebPreferences.h"
-#include "qquickwebpage_p.h"
-#include "qquickwebview_p.h"
-#include "qwebkittest_p.h"
-#include <QPointF>
-#include <QTransform>
-#include <QWheelEvent>
-#include <QtQuick/qquickitem.h>
-#include <wtf/PassOwnPtr.h>
-
-namespace WebKit {
-
-static const int kScaleAnimationDurationMillis = 250;
-
-// UPDATE DEFERRING (SUSPEND/RESUME)
-// =================================
-//
-// When interaction with the content, either by animating or by the hand of the user,
-// it is important to ensure smooth animations of at least 60fps in order to give a
-// good user experience.
-//
-// In order to do this we need to get rid of unknown factors. These include device
-// sensors (geolocation, orientation updates etc), CSS3 animations, JavaScript
-// exectution, sub resource loads etc. We do this by emitting suspend and resume
-// signals, which are then handled by the viewport and propagates to the right place.
-//
-// For this reason the ViewportUpdateDeferrer guard must be used when we interact
-// or animate the content.
-//
-// It should be noted that when we update content properties, we might receive notify
-// signals send my the content item itself, and care should be taken to not act on
-// these unconditionally. An example of this is the pinch zoom, which changes the
-// position and will thus result in a QQuickWebPage::geometryChanged() signal getting
-// emitted.
-//
-// If something should only be executed during update deferring, it is possible to
-// check for that using ASSERT(m_suspendCount).
-
-class ViewportUpdateDeferrer {
-public:
- enum SuspendContentFlag { DeferUpdate, DeferUpdateAndSuspendContent };
- ViewportUpdateDeferrer(QtViewportInteractionEngine* engine, SuspendContentFlag suspendContentFlag = DeferUpdate)
- : engine(engine)
- {
- engine->m_suspendCount++;
-
- // There is no need to suspend content for immediate updates
- // only during animations or longer gestures.
- if (suspendContentFlag == DeferUpdateAndSuspendContent)
- engine->suspendPageContent();
- }
-
- ~ViewportUpdateDeferrer()
- {
- if (--(engine->m_suspendCount))
- return;
-
- engine->resumePageContent();
-
- // Make sure that tiles all around the viewport will be requested.
- engine->informVisibleContentChange(QPointF());
- }
-
-private:
- QtViewportInteractionEngine* const engine;
-};
-
-void QtViewportInteractionEngine::suspendPageContent()
-{
- if (m_hasSuspendedContent)
- return;
-
- m_hasSuspendedContent = true;
- m_webPageProxy->suspendActiveDOMObjectsAndAnimations();
-}
-
-void QtViewportInteractionEngine::resumePageContent()
-{
- if (!m_hasSuspendedContent)
- return;
- m_hasSuspendedContent = false;
- m_webPageProxy->resumeActiveDOMObjectsAndAnimations();
-}
-
-// A floating point compare with absolute error.
-static inline bool fuzzyCompare(qreal a, qreal b, qreal epsilon)
-{
- return qAbs(a - b) < epsilon;
-}
-
-inline qreal QtViewportInteractionEngine::cssScaleFromItem(qreal itemScale) const
-{
- return itemScale / m_devicePixelRatio;
-}
-
-inline qreal QtViewportInteractionEngine::itemScaleFromCSS(qreal cssScale) const
-{
- return cssScale * m_devicePixelRatio;
-}
-
-inline qreal QtViewportInteractionEngine::itemCoordFromCSS(qreal value) const
-{
- return value * m_devicePixelRatio;
-}
-
-static inline QPointF boundPosition(const QPointF minPosition, const QPointF& position, const QPointF& maxPosition)
-{
- return QPointF(qBound(minPosition.x(), position.x(), maxPosition.x()),
- qBound(minPosition.y(), position.y(), maxPosition.y()));
-}
-
-inline QRectF QtViewportInteractionEngine::itemRectFromCSS(const QRectF& cssRect) const
-{
- QRectF itemRect;
-
- itemRect.setX(itemCoordFromCSS(cssRect.x()));
- itemRect.setY(itemCoordFromCSS(cssRect.y()));
- itemRect.setWidth(itemCoordFromCSS(cssRect.width()));
- itemRect.setHeight(itemCoordFromCSS(cssRect.height()));
-
- return itemRect;
-}
-
-QtViewportInteractionEngine::QtViewportInteractionEngine(WebKit::WebPageProxy* proxy, QQuickWebView* viewportItem, QQuickWebPage* pageItem)
- : m_webPageProxy(proxy)
- , m_viewportItem(viewportItem)
- , m_pageItem(pageItem)
- , m_allowsUserScaling(false)
- , m_minimumScale(1)
- , m_maximumScale(1)
- , m_devicePixelRatio(1)
- , m_suspendCount(0)
- , m_hasSuspendedContent(false)
- , m_hadUserInteraction(false)
- , m_scaleAnimation(new ScaleAnimation(this))
- , m_pinchStartScale(-1)
- , m_lastCommittedScale(-1)
- , m_zoomOutScale(0.0)
-{
- connect(m_viewportItem, SIGNAL(movementStarted()), SLOT(flickMoveStarted()), Qt::DirectConnection);
- connect(m_viewportItem, SIGNAL(movementEnded()), SLOT(flickMoveEnded()), Qt::DirectConnection);
-
- connect(m_scaleAnimation, SIGNAL(valueChanged(QVariant)),
- SLOT(scaleAnimationValueChanged(QVariant)), Qt::DirectConnection);
- connect(m_scaleAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)),
- SLOT(scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), Qt::DirectConnection);
-}
-
-QtViewportInteractionEngine::~QtViewportInteractionEngine()
-{
-}
-
-qreal QtViewportInteractionEngine::innerBoundedCSSScale(qreal cssScale) const
-{
- return qBound(m_minimumScale, cssScale, m_maximumScale);
-}
-
-qreal QtViewportInteractionEngine::outerBoundedCSSScale(qreal cssScale) const
-{
- if (m_allowsUserScaling) {
- // Bounded by [0.1, 10.0] like the viewport meta code in WebCore.
- qreal hardMin = qMax<qreal>(0.1, qreal(0.5) * m_minimumScale);
- qreal hardMax = qMin<qreal>(10, qreal(2.0) * m_maximumScale);
- return qBound(hardMin, cssScale, hardMax);
- }
- return innerBoundedCSSScale(cssScale);
-}
-
-void QtViewportInteractionEngine::viewportAttributesChanged(const WebCore::ViewportAttributes& newAttributes)
-{
- m_rawAttributes = newAttributes;
- WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
-
- {
- // FIXME: Resetting here is wrong, it should happen only for the first
- // viewport change for a given page and first when we paint the page for
- // the first time.
-
- m_hadUserInteraction = false;
-
- m_zoomOutScale = 0.0;
- m_scaleStack.clear();
-
- // This part below should go fully away when the above plan is implemented.
-
- m_viewportItem->cancelFlick();
- m_scaleAnimation->stop();
-
- m_scaleUpdateDeferrer.clear();
- m_scrollUpdateDeferrer.clear();
- m_touchUpdateDeferrer.clear();
- m_animationUpdateDeferrer.clear();
- ASSERT(!m_suspendCount);
- ASSERT(!m_hasSuspendedContent);
- }
-
- m_devicePixelRatio = m_rawAttributes.devicePixelRatio; // Should return value from the webPageProxy.
- m_allowsUserScaling = !!m_rawAttributes.userScalable;
- m_minimumScale = m_rawAttributes.minimumScale;
- m_maximumScale = m_rawAttributes.maximumScale;
-
- if (!m_hadUserInteraction && !m_hasSuspendedContent) {
- ASSERT(m_pinchStartScale == -1);
- // Emits contentsScaleChanged();
- setCSSScale(m_rawAttributes.initialScale);
- }
-
- emit m_viewportItem->experimental()->test()->viewportChanged();
-
- // If the web app successively changes the viewport on purpose
- // it wants to be in control and we should disable animations.
- ViewportUpdateDeferrer guard(this);
- setPageItemRectVisible(nearestValidBounds());
-}
-
-void QtViewportInteractionEngine::pageContentsSizeChanged(const QSize& newSize, const QSize& viewportSize)
-{
- float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, viewportSize, newSize);
-
- if (!qFuzzyCompare(minimumScale, m_rawAttributes.minimumScale)) {
- m_minimumScale = minimumScale;
- emit m_viewportItem->experimental()->test()->viewportChanged();
-
- if (!m_hadUserInteraction && !m_hasSuspendedContent) {
- // Emits contentsScaleChanged();
- setCSSScale(minimumScale);
- }
- }
-
- // Emit for testing purposes, so that it can be verified that
- // we didn't do scale adjustment.
- emit m_viewportItem->experimental()->test()->contentsScaleCommitted();
-
- ViewportUpdateDeferrer guard(this);
- setPageItemRectVisible(nearestValidBounds());
-}
-
-void QtViewportInteractionEngine::setPageItemRectVisible(const QRectF& itemRect)
-{
- ASSERT_WITH_MESSAGE(m_suspendCount,
- "setPageItemRectVisible has to be guarded using a ViewportUpdateDeferrer.");
-
- if (itemRect.isEmpty())
- return;
-
- qreal itemScale = m_viewportItem->width() / itemRect.width();
-
- m_pageItem->setContentsScale(itemScale);
-
- // To animate the position together with the scale we multiply the position with the current scale
- // and add it to the page position (displacement on the flickable contentItem because of additional items).
- QPointF newPosition(m_pageItem->pos() + (itemRect.topLeft() * itemScale));
-
- m_viewportItem->setContentPos(newPosition);
-}
-
-// Ease out overshoot of 1.25 combined with ease in correction of 0.25. Both quadratic to have physical motion.
-static qreal physicalOvershoot(qreal t)
-{
- return (-t * (t - 2)) * 1.25 - (t * t) * 0.25;
-}
-
-void QtViewportInteractionEngine::animatePageItemRectVisible(const QRectF& itemRect)
-{
- ASSERT(m_scaleAnimation->state() == QAbstractAnimation::Stopped);
-
- ASSERT(!scrollAnimationActive());
- if (scrollAnimationActive())
- return;
-
- QRectF currentPageItemRectVisible = m_viewportItem->mapRectToWebContent(m_viewportItem->boundingRect());
- if (itemRect == currentPageItemRectVisible)
- return;
-
- QEasingCurve easingCurve;
- easingCurve.setCustomType(physicalOvershoot);
-
- m_scaleAnimation->setDuration(kScaleAnimationDurationMillis);
- m_scaleAnimation->setEasingCurve(easingCurve);
-
- m_scaleAnimation->setStartValue(currentPageItemRectVisible);
- m_scaleAnimation->setEndValue(itemRect);
-
- m_scaleAnimation->start();
-}
-
-void QtViewportInteractionEngine::flickMoveStarted()
-{
- Q_ASSERT(m_viewportItem->isMoving());
- m_scrollUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent));
-
- m_lastScrollPosition = m_viewportItem->contentPos();
- connect(m_viewportItem, SIGNAL(contentXChanged()), SLOT(pageItemPositionChanged()));
- connect(m_viewportItem, SIGNAL(contentYChanged()), SLOT(pageItemPositionChanged()));
-}
-
-void QtViewportInteractionEngine::flickMoveEnded()
-{
- Q_ASSERT(!m_viewportItem->isMoving());
- // This method is called on the end of the pan or pan kinetic animation.
- m_scrollUpdateDeferrer.clear();
-
- m_lastScrollPosition = QPointF();
- disconnect(m_viewportItem, SIGNAL(contentXChanged()), this, SLOT(pageItemPositionChanged()));
- disconnect(m_viewportItem, SIGNAL(contentYChanged()), this, SLOT(pageItemPositionChanged()));
-}
-
-void QtViewportInteractionEngine::pageItemPositionChanged()
-{
- QPointF newPosition = m_viewportItem->contentPos();
-
- informVisibleContentChange(m_lastScrollPosition - newPosition);
-
- m_lastScrollPosition = newPosition;
-}
-
-void QtViewportInteractionEngine::pageContentPositionRequested(const QPoint& cssPosition)
-{
- // Ignore the request if suspended. Can only happen due to delay in event delivery.
- if (m_suspendCount)
- return;
-
- qreal endItemScale = m_pageItem->contentsScale(); // Stay at same scale.
-
- QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale);
- QPointF endPosition = boundPosition(endPosRange.topLeft(), cssPosition * endItemScale, endPosRange.bottomRight());
-
- QRectF endVisibleContentRect(endPosition / endItemScale, m_viewportItem->boundingRect().size() / endItemScale);
-
- ViewportUpdateDeferrer guard(this);
- setPageItemRectVisible(endVisibleContentRect);
-}
-
-void QtViewportInteractionEngine::scaleAnimationStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/)
-{
- switch (newState) {
- case QAbstractAnimation::Running:
- m_viewportItem->cancelFlick();
- ASSERT(!m_animationUpdateDeferrer);
- m_animationUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent));
- break;
- case QAbstractAnimation::Stopped:
- m_animationUpdateDeferrer.clear();
- break;
- default:
- break;
- }
-}
-
-void QtViewportInteractionEngine::scaleAnimationValueChanged(QVariant value)
-{
- setPageItemRectVisible(value.toRectF());
-}
-
-void QtViewportInteractionEngine::touchBegin()
-{
- m_hadUserInteraction = true;
-
- // Prevents resuming the page between the user's flicks of the page while the animation is running.
- if (scrollAnimationActive())
- m_touchUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent));
-}
-
-void QtViewportInteractionEngine::touchEnd()
-{
- m_touchUpdateDeferrer.clear();
-}
-
-QRectF QtViewportInteractionEngine::computePosRangeForPageItemAtScale(qreal itemScale) const
-{
- const QSizeF contentItemSize = m_pageItem->contentsSize() * itemScale;
- const QSizeF viewportItemSize = m_viewportItem->boundingRect().size();
-
- const qreal horizontalRange = contentItemSize.width() - viewportItemSize.width();
- const qreal verticalRange = contentItemSize.height() - viewportItemSize.height();
-
- return QRectF(QPointF(0, 0), QSizeF(horizontalRange, verticalRange));
-}
-
-void QtViewportInteractionEngine::focusEditableArea(const QRectF& caretArea, const QRectF& targetArea)
-{
- // This can only happen as a result of a user interaction.
- ASSERT(m_hadUserInteraction);
-
- QRectF endArea = itemRectFromCSS(targetArea);
-
- qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(2.0));
- const QRectF viewportRect = m_viewportItem->boundingRect();
-
- qreal x;
- const qreal borderOffset = 10;
- if ((endArea.width() + borderOffset) * endItemScale <= viewportRect.width()) {
- // Center the input field in the middle of the view, if it is smaller than
- // the view at the scale target.
- x = viewportRect.center().x() - endArea.width() * endItemScale / 2.0;
- } else {
- // Ensure that the caret always has borderOffset contents pixels to the right
- // of it, and secondarily (if possible), that the area has borderOffset
- // contents pixels to the left of it.
- qreal caretOffset = itemCoordFromCSS(caretArea.x()) - endArea.x();
- x = qMin(viewportRect.width() - (caretOffset + borderOffset) * endItemScale, borderOffset * endItemScale);
- }
-
- const QPointF hotspot = QPointF(endArea.x(), endArea.center().y());
- const QPointF viewportHotspot = QPointF(x, /* FIXME: visibleCenter */ viewportRect.center().y());
-
- QPointF endPosition = hotspot * endItemScale - viewportHotspot;
- QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale);
-
- endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight());
-
- QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale);
-
- animatePageItemRectVisible(endVisibleContentRect);
-}
-
-void QtViewportInteractionEngine::zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea)
-{
- // This can only happen as a result of a user interaction.
- ASSERT(m_hadUserInteraction);
-
- if (!targetArea.isValid())
- return;
-
- if (m_suspendCount)
- return;
-
- const int margin = 10; // We want at least a little bit of margin.
- QRectF endArea = itemRectFromCSS(targetArea.adjusted(-margin, -margin, margin, margin));
-
- const QRectF viewportRect = m_viewportItem->boundingRect();
-
- qreal targetCSSScale = viewportRect.size().width() / endArea.size().width();
- qreal endCSSScale = innerBoundedCSSScale(qMin(targetCSSScale, qreal(2.5)));
- qreal endItemScale = itemScaleFromCSS(endCSSScale);
- qreal currentScale = m_pageItem->contentsScale();
-
- // We want to end up with the target area filling the whole width of the viewport (if possible),
- // and centralized vertically where the user requested zoom. Thus our hotspot is the center of
- // the targetArea x-wise and the requested zoom position, y-wise.
- const QPointF hotspot = QPointF(endArea.center().x(), itemCoordFromCSS(touchPoint.y()));
- const QPointF viewportHotspot = viewportRect.center();
-
- QPointF endPosition = hotspot * endCSSScale - viewportHotspot;
-
- QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale);
- endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight());
-
- QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale);
-
- enum { ZoomIn, ZoomBack, ZoomOut, NoZoom } zoomAction = ZoomIn;
-
- if (!m_scaleStack.isEmpty()) {
- // Zoom back out if attempting to scale to the same current scale, or
- // attempting to continue scaling out from the inner most level.
- // Use fuzzy compare with a fixed error to be able to deal with largish differences due to pixel rounding.
- if (fuzzyCompare(endItemScale, currentScale, 0.01)) {
- // If moving the viewport would expose more of the targetRect and move at least 40 pixels, update position but do not scale out.
- QRectF currentContentRect(m_viewportItem->contentPos() / currentScale, viewportRect.size() / currentScale);
- QRectF targetIntersection = endVisibleContentRect.intersected(targetArea);
- if (!currentContentRect.contains(targetIntersection) && (qAbs(endVisibleContentRect.top() - currentContentRect.top()) >= 40 || qAbs(endVisibleContentRect.left() - currentContentRect.left()) >= 40))
- zoomAction = NoZoom;
- else
- zoomAction = ZoomBack;
- } else if (fuzzyCompare(endItemScale, m_zoomOutScale, 0.01))
- zoomAction = ZoomBack;
- else if (endItemScale < currentScale)
- zoomAction = ZoomOut;
- }
-
- switch (zoomAction) {
- case ZoomIn:
- m_scaleStack.append(ScaleStackItem(currentScale, m_viewportItem->contentPos().x()));
- m_zoomOutScale = endItemScale;
- break;
- case ZoomBack: {
- ScaleStackItem lastScale = m_scaleStack.takeLast();
- endItemScale = lastScale.scale;
- endCSSScale = cssScaleFromItem(lastScale.scale);
- // Recalculate endPosition and bound it according to new scale.
- endPosition.setY(hotspot.y() * endCSSScale - viewportHotspot.y());
- endPosition.setX(lastScale.xPosition);
- endPosRange = computePosRangeForPageItemAtScale(endItemScale);
- endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight());
- endVisibleContentRect = QRectF(endPosition / endItemScale, viewportRect.size() / endItemScale);
- break;
- }
- case ZoomOut:
- // Unstack all scale-levels deeper than the new level, so a zoom-back won't end up zooming in.
- while (!m_scaleStack.isEmpty() && m_scaleStack.last().scale >= endItemScale)
- m_scaleStack.removeLast();
- m_zoomOutScale = endItemScale;
- break;
- case NoZoom:
- break;
- }
-
- animatePageItemRectVisible(endVisibleContentRect);
-}
-
-QRectF QtViewportInteractionEngine::nearestValidBounds() const
-{
- qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(currentCSSScale()));
-
- const QRectF viewportRect = m_viewportItem->boundingRect();
- QPointF viewportHotspot = viewportRect.center();
-
- QPointF endPosition = m_viewportItem->mapToWebContent(viewportHotspot) * endItemScale - viewportHotspot;
-
- QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale);
- endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight());
-
- QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale);
-
- return endVisibleContentRect;
-}
-
-void QtViewportInteractionEngine::setCSSScale(qreal scale)
-{
- ViewportUpdateDeferrer guard(this);
-
- qreal newScale = innerBoundedCSSScale(scale);
- m_pageItem->setContentsScale(itemScaleFromCSS(newScale));
-}
-
-qreal QtViewportInteractionEngine::currentCSSScale() const
-{
- return cssScaleFromItem(m_pageItem->contentsScale());
-}
-
-bool QtViewportInteractionEngine::scrollAnimationActive() const
-{
- return m_viewportItem->isFlicking();
-}
-
-bool QtViewportInteractionEngine::panGestureActive() const
-{
- return m_viewportItem->isDragging();
-}
-
-void QtViewportInteractionEngine::panGestureStarted(const QPointF& position, qint64 eventTimestampMillis)
-{
- // This can only happen as a result of a user interaction.
- ASSERT(m_hadUserInteraction);
-
- m_viewportItem->handleFlickableMousePress(position, eventTimestampMillis);
- m_lastPinchCenterInViewportCoordinates = position;
-}
-
-void QtViewportInteractionEngine::panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis)
-{
- m_viewportItem->handleFlickableMouseMove(position, eventTimestampMillis);
- m_lastPinchCenterInViewportCoordinates = position;
-}
-
-void QtViewportInteractionEngine::panGestureEnded(const QPointF& position, qint64 eventTimestampMillis)
-{
- m_viewportItem->handleFlickableMouseRelease(position, eventTimestampMillis);
- m_lastPinchCenterInViewportCoordinates = position;
-}
-
-void QtViewportInteractionEngine::panGestureCancelled()
-{
- // Reset the velocity samples of the flickable.
- // This should only be called by the recognizer if we have a recognized
- // pan gesture and receive a touch event with multiple touch points
- // (ie. transition to a pinch gesture) as it does not move the content
- // back inside valid bounds.
- // When the pinch gesture ends, the content is positioned and scaled
- // back to valid boundaries.
- m_viewportItem->cancelFlick();
-}
-
-bool QtViewportInteractionEngine::scaleAnimationActive() const
-{
- return m_scaleAnimation->state() == QAbstractAnimation::Running;
-}
-
-void QtViewportInteractionEngine::cancelScrollAnimation()
-{
- if (!scrollAnimationActive())
- return;
-
- // If the pan gesture recognizer receives a touch begin event
- // during an ongoing kinetic scroll animation of a previous
- // pan gesture, the animation is stopped and the content is
- // immediately positioned back to valid boundaries.
-
- m_viewportItem->cancelFlick();
- ViewportUpdateDeferrer guard(this);
- setPageItemRectVisible(nearestValidBounds());
-}
-
-void QtViewportInteractionEngine::interruptScaleAnimation()
-{
- // This interrupts the scale animation exactly where it is, even if it is out of bounds.
- m_scaleAnimation->stop();
-}
-
-bool QtViewportInteractionEngine::pinchGestureActive() const
-{
- return m_pinchStartScale > 0;
-}
-
-void QtViewportInteractionEngine::pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates)
-{
- // This can only happen as a result of a user interaction.
- ASSERT(m_hadUserInteraction);
-
- if (!m_allowsUserScaling)
- return;
-
- m_scaleStack.clear();
- m_zoomOutScale = 0.0;
-
- m_scaleUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent));
-
- m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates;
- m_pinchStartScale = m_pageItem->contentsScale();
-}
-
-void QtViewportInteractionEngine::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor)
-{
- ASSERT(m_suspendCount);
-
- if (!m_allowsUserScaling)
- return;
-
- // Changes of the center position should move the page even if the zoom factor
- // does not change.
- const qreal cssScale = cssScaleFromItem(m_pinchStartScale * totalScaleFactor);
-
- // Allow zooming out beyond mimimum scale on pages that do not explicitly disallow it.
- const qreal targetCSSScale = outerBoundedCSSScale(cssScale);
-
- scaleContent(m_viewportItem->mapToWebContent(pinchCenterInViewportCoordinates), targetCSSScale);
-
- const QPointF positionDiff = pinchCenterInViewportCoordinates - m_lastPinchCenterInViewportCoordinates;
- m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates;
-
- m_viewportItem->setContentPos(m_viewportItem->contentPos() - positionDiff);
-}
-
-void QtViewportInteractionEngine::pinchGestureEnded()
-{
- ASSERT(m_suspendCount);
-
- if (!m_allowsUserScaling)
- return;
-
- m_pinchStartScale = -1;
-
- animatePageItemRectVisible(nearestValidBounds());
- m_scaleUpdateDeferrer.clear(); // Clear after starting potential animation, which takes over deferring.
-}
-
-void QtViewportInteractionEngine::pinchGestureCancelled()
-{
- m_pinchStartScale = -1;
- m_scaleUpdateDeferrer.clear();
-}
-
-QRect QtViewportInteractionEngine::visibleContentsRect() const
-{
- const QRectF visibleRect(m_viewportItem->boundingRect().intersected(m_pageItem->boundingRect()));
-
- // We avoid using toAlignedRect() because it produces inconsistent width and height.
- QRectF mappedRect(m_viewportItem->mapRectToWebContent(visibleRect));
- return QRect(floor(mappedRect.x()), floor(mappedRect.y()), floor(mappedRect.width()), floor(mappedRect.height()));
-}
-
-void QtViewportInteractionEngine::informVisibleContentChange(const QPointF& trajectoryVector)
-{
- DrawingAreaProxy* drawingArea = m_webPageProxy->drawingArea();
- if (!drawingArea)
- return;
-
- if (m_lastVisibleContentsRect == visibleContentsRect())
- return;
-
- qreal scale = m_pageItem->contentsScale();
-
- if (scale != m_lastCommittedScale)
- emit m_viewportItem->experimental()->test()->contentsScaleCommitted();
- m_lastCommittedScale = scale;
- m_lastVisibleContentsRect = visibleContentsRect();
-
- drawingArea->setVisibleContentsRect(visibleContentsRect(), scale, trajectoryVector, m_viewportItem->contentPos());
-
- // Ensure that updatePaintNode is always called before painting.
- m_pageItem->update();
-}
-
-void QtViewportInteractionEngine::viewportItemSizeChanged()
-{
- QSize viewportSize = m_viewportItem->boundingRect().size().toSize();
-
- if (viewportSize.isEmpty())
- return;
-
- // FIXME: This is wrong, add QML api!
- WebPreferences* wkPrefs = m_webPageProxy->pageGroup()->preferences();
- wkPrefs->setDeviceWidth(viewportSize.width());
- wkPrefs->setDeviceHeight(viewportSize.height());
-
- // Let the WebProcess know about the new viewport size, so that
- // it can resize the content accordingly.
- m_webPageProxy->setViewportSize(viewportSize);
-
- informVisibleContentChange(QPointF());
-}
-
-void QtViewportInteractionEngine::scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale)
-{
- QPointF oldPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates);
- m_pageItem->setContentsScale(itemScaleFromCSS(cssScale));
- QPointF newPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates);
-
- m_viewportItem->setContentPos(m_viewportItem->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport));
-}
-
-} // namespace WebKit
-
-#include "moc_QtViewportInteractionEngine.cpp"
-
-