diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-03-20 18:54:42 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-03-25 17:44:32 +0100 |
commit | f17185389d49fd4781e6745df59a71ad0270a1d0 (patch) | |
tree | 84db31d6f6180cd5bbbc9fa903b7b1e372fde155 /Source/WebKit2/UIProcess/qt | |
parent | 2f903ee40150a6db52749a2a8ac086d9fbadbbbc (diff) | |
download | qtwebkit-f17185389d49fd4781e6745df59a71ad0270a1d0.tar.gz |
Refactor handling of content suspension to properly cover corner cases
https://bugs.webkit.org/show_bug.cgi?id=111751
This is a back-port from upstream patch http://trac.webkit.org/changeset/146355
Reviewed by Jocelyn Turcotte.
The current suspend / resume infrastructure turned out to be insufficient to cover
all corner cases during transitions between gestures of complex gesture chains.
The requirements for robust suspend / resume handling are:
- Keep the content suspended while the user is continuously interacting,
eg. does not lift the finger between transition from a pan to a pinch gesture
and vice versa.
- The content should not be suspended unnecessarily (like for a tap gesture),
only during panning and scroll animation (flick), as well as pinch zoom and scale
animation (also includes double-tap-to-zoom).
- The content should never end up stuck in suspended state after long gesture
chains and continuous interaction.
This patch reintroduces reference counting based suspension in form of a new
ViewportInteractionTracker member class to make it possible to reliably control the
suspend / resume cycles during scrolling and scaling.
During continuous gestures, while the user is interacting, the reference count is
increased without actually suspending the content to prevent resuming unnecessarily
during continuous interaction. At the same time this also assures that the page is
not suspended for simple tap gestures, which was a side-effect of the previous
approach based on update deferrers.
The newly added functionality replaces boolean members that tried to achive the
above requirements.
Additionally this patch also removes the redundant m_hasSuspendedContent member
from the PageViewportController since WebPageProxy already keeps this information.
Change-Id: Id9b55d37c7ad839a27029e92872f36bbf202e660
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'Source/WebKit2/UIProcess/qt')
-rw-r--r-- | Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp | 79 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h | 26 |
2 files changed, 77 insertions, 28 deletions
diff --git a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp index c0eb16ab9..61f2aaf57 100644 --- a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp +++ b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp @@ -23,12 +23,14 @@ #include "config.h" #include "PageViewportControllerClientQt.h" +#include "WebPageProxy.h" #include "qquickwebpage_p.h" #include "qquickwebview_p.h" #include "qwebkittest_p.h" #include <QPointF> #include <QTransform> #include <QtQuick/qquickitem.h> +#include <WKAPICast.h> #include <WebCore/FloatRect.h> #include <WebCore/FloatSize.h> @@ -41,12 +43,14 @@ static const int kScaleAnimationDurationMillis = 250; PageViewportControllerClientQt::PageViewportControllerClientQt(QQuickWebView* viewportItem, QQuickWebPage* pageItem) : m_viewportItem(viewportItem) , m_pageItem(pageItem) + , m_scaleChange(this) + , m_scrollChange(this) + , m_touchInteraction(this, false /* shouldSuspend */) , m_scaleAnimation(new ScaleAnimation(this)) + , m_activeInteractionCount(0) , m_pinchStartScale(-1) , m_lastCommittedScale(-1) , m_zoomOutScale(0) - , m_isUserInteracting(false) - , m_ignoreViewportChanges(false) { m_scaleAnimation->setDuration(kScaleAnimationDurationMillis); m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic); @@ -76,6 +80,32 @@ void PageViewportControllerClientQt::ScaleAnimation::updateCurrentValue(const QV m_controllerClient->setContentRectVisiblePositionAtScale(itemRect.topLeft(), itemScale); } +void PageViewportControllerClientQt::ViewportInteractionTracker::begin() +{ + if (m_inProgress) + return; + + m_inProgress = true; + + if (m_shouldSuspend) + toImpl(m_controllerClient->m_viewportItem->pageRef())->suspendActiveDOMObjectsAndAnimations(); + + ++(m_controllerClient->m_activeInteractionCount); +} + +void PageViewportControllerClientQt::ViewportInteractionTracker::end() +{ + if (!m_inProgress) + return; + + m_inProgress = false; + + ASSERT(m_controllerClient->m_activeInteractionCount > 0); + + if (!(--(m_controllerClient->m_activeInteractionCount))) + toImpl(m_controllerClient->m_viewportItem->pageRef())->resumeActiveDOMObjectsAndAnimations(); +} + PageViewportControllerClientQt::~PageViewportControllerClientQt() { } @@ -103,7 +133,8 @@ void PageViewportControllerClientQt::animateContentRectVisible(const QRectF& con QRectF viewportRectInContentCoords = m_viewportItem->mapRectToWebContent(m_viewportItem->boundingRect()); if (contentRect == viewportRectInContentCoords) { - m_controller->resumeContent(); + m_scaleChange.end(); + updateViewportController(); return; } @@ -121,22 +152,20 @@ void PageViewportControllerClientQt::animateContentRectVisible(const QRectF& con void PageViewportControllerClientQt::flickMoveStarted() { - m_controller->suspendContent(); - + m_scrollChange.begin(); m_lastScrollPosition = m_viewportItem->contentPos(); } void PageViewportControllerClientQt::flickMoveEnded() { // This method is called on the end of the pan or pan kinetic animation. - - if (!m_isUserInteracting) - m_controller->resumeContent(); + m_scrollChange.end(); + updateViewportController(); } void PageViewportControllerClientQt::pageItemPositionChanged() { - if (m_ignoreViewportChanges) + if (m_scaleChange.inProgress()) return; QPointF newPosition = m_viewportItem->contentPos(); @@ -150,13 +179,11 @@ void PageViewportControllerClientQt::scaleAnimationStateChanged(QAbstractAnimati { switch (newState) { case QAbstractAnimation::Running: - m_ignoreViewportChanges = true; - m_viewportItem->cancelFlick(); - m_controller->suspendContent(); + m_scaleChange.begin(); break; case QAbstractAnimation::Stopped: - m_ignoreViewportChanges = false; - m_controller->resumeContent(); + m_scaleChange.end(); + updateViewportController(); break; default: break; @@ -167,13 +194,14 @@ void PageViewportControllerClientQt::touchBegin() { m_controller->setHadUserInteraction(true); - // Prevents resuming the page between the user's flicks of the page. - m_isUserInteracting = true; + // Prevent resuming the page during transition between gestures while the user is interacting. + // The content is suspended as soon as a pan or pinch gesture or an animation is started. + m_touchInteraction.begin(); } void PageViewportControllerClientQt::touchEnd() { - m_isUserInteracting = false; + m_touchInteraction.end(); } void PageViewportControllerClientQt::focusEditableArea(const QRectF& caretArea, const QRectF& targetArea) @@ -217,7 +245,7 @@ void PageViewportControllerClientQt::zoomToAreaGestureEnded(const QPointF& touch if (!targetArea.isValid()) return; - if (m_controller->hasSuspendedContent()) + if (m_scrollChange.inProgress() || m_scaleChange.inProgress()) return; const float margin = 10; // We want at least a little bit of margin. @@ -425,9 +453,7 @@ void PageViewportControllerClientQt::pinchGestureStarted(const QPointF& pinchCen return; clearRelativeZoomState(); - - m_ignoreViewportChanges = true; - m_controller->suspendContent(); + m_scaleChange.begin(); m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; m_pinchStartScale = m_pageItem->contentsScale(); @@ -435,11 +461,12 @@ void PageViewportControllerClientQt::pinchGestureStarted(const QPointF& pinchCen void PageViewportControllerClientQt::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor) { - ASSERT(m_controller->hasSuspendedContent()); + ASSERT(m_scaleChange.inProgress()); if (!m_controller->allowsUserScaling()) return; + ASSERT(m_pinchStartScale > 0); // Changes of the center position should move the page even if the zoom factor does not change. const qreal pinchScale = m_pinchStartScale * totalScaleFactor; @@ -456,12 +483,11 @@ void PageViewportControllerClientQt::pinchGestureRequestUpdate(const QPointF& pi void PageViewportControllerClientQt::pinchGestureEnded() { - ASSERT(m_controller->hasSuspendedContent()); + ASSERT(m_scaleChange.inProgress()); if (!m_controller->allowsUserScaling()) return; - m_ignoreViewportChanges = false; m_pinchStartScale = -1; // This will take care of resuming the content, even if no animation was performed. @@ -471,7 +497,8 @@ void PageViewportControllerClientQt::pinchGestureEnded() void PageViewportControllerClientQt::pinchGestureCancelled() { m_pinchStartScale = -1; - m_controller->resumeContent(); + m_scaleChange.end(); + updateViewportController(); } void PageViewportControllerClientQt::didChangeContentsSize(const IntSize& newSize) @@ -482,7 +509,7 @@ void PageViewportControllerClientQt::didChangeContentsSize(const IntSize& newSiz // we didn't do scale adjustment. emit m_viewportItem->experimental()->test()->contentsScaleCommitted(); - if (!m_controller->hasSuspendedContent()) + if (!m_scaleChange.inProgress() && !m_scrollChange.inProgress()) setContentsRectToNearestValidBounds(); } diff --git a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h index 687f29193..22c4c3d3c 100644 --- a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h +++ b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h @@ -103,6 +103,24 @@ private: virtual void updateCurrentValue(const QVariant&); }; + class ViewportInteractionTracker { + public: + ViewportInteractionTracker(PageViewportControllerClientQt* client, bool shouldSuspend = true) + : m_controllerClient(client) + , m_shouldSuspend(shouldSuspend) + , m_inProgress(false) + { } + + void begin(); + void end(); + bool inProgress() const { return m_inProgress; } + + private: + PageViewportControllerClientQt* m_controllerClient; + bool m_shouldSuspend; + bool m_inProgress; + }; + struct ScaleStackItem { ScaleStackItem(qreal scale, qreal xPosition) : scale(scale) @@ -113,6 +131,7 @@ private: qreal xPosition; }; + friend class ViewportInteractionTracker; friend class ScaleAnimation; friend class ::QWebKitTest; @@ -130,15 +149,18 @@ private: void scaleContent(qreal itemScale, const QPointF& centerInCSSCoordinates = QPointF()); void clearRelativeZoomState(); + ViewportInteractionTracker m_scaleChange; + ViewportInteractionTracker m_scrollChange; + ViewportInteractionTracker m_touchInteraction; + ScaleAnimation* m_scaleAnimation; QPointF m_lastPinchCenterInViewportCoordinates; QPointF m_lastScrollPosition; + int m_activeInteractionCount; qreal m_pinchStartScale; qreal m_lastCommittedScale; qreal m_zoomOutScale; QList<ScaleStackItem> m_scaleStack; - bool m_isUserInteracting; - bool m_ignoreViewportChanges; }; } // namespace WebKit |