summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/PageViewportController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/UIProcess/PageViewportController.cpp')
-rw-r--r--Source/WebKit2/UIProcess/PageViewportController.cpp107
1 files changed, 89 insertions, 18 deletions
diff --git a/Source/WebKit2/UIProcess/PageViewportController.cpp b/Source/WebKit2/UIProcess/PageViewportController.cpp
index e42006a14..02fd3b699 100644
--- a/Source/WebKit2/UIProcess/PageViewportController.cpp
+++ b/Source/WebKit2/UIProcess/PageViewportController.cpp
@@ -54,9 +54,6 @@ ViewportUpdateDeferrer::~ViewportUpdateDeferrer()
return;
m_controller->resumeContent();
-
- // Make sure that tiles all around the viewport will be requested.
- m_controller->syncVisibleContents();
}
PageViewportController::PageViewportController(WebKit::WebPageProxy* proxy, PageViewportControllerClient* client)
@@ -109,15 +106,65 @@ FloatPoint PageViewportController::clampViewportToContents(const WebCore::FloatP
return FloatPoint(clampTo(viewportPos.x(), 0.f, horizontalRange), clampTo(viewportPos.y(), 0.f, verticalRange));
}
-void PageViewportController::didChangeContentsSize(const IntSize& newSize)
+void PageViewportController::didCommitLoad()
{
- if (m_viewportSize.isEmpty() || newSize.isEmpty())
- return;
+ // Do not count the previous committed page contents as covered.
+ m_lastFrameCoveredRect = FloatRect();
+
+ // Reset the position to the top, page/history scroll requests may override this before we re-enable rendering.
+ applyPositionAfterRenderingContents(FloatPoint());
+}
+void PageViewportController::didChangeContentsSize(const IntSize& newSize)
+{
m_contentsSize = newSize;
updateMinimumScaleToFit();
+}
+
+void PageViewportController::didRenderFrame(const IntSize& contentsSize, const IntRect& coveredRect)
+{
+ if (m_clientContentsSize != contentsSize) {
+ m_clientContentsSize = contentsSize;
+ // Only update the viewport's contents dimensions along with its render if the
+ // size actually changed since animations on the page trigger DidRenderFrame
+ // messages without causing dimension changes.
+ m_client->didChangeContentsSize(contentsSize);
+ }
+
+ m_lastFrameCoveredRect = coveredRect;
+
+ // Apply any scale or scroll position we locked to be set on the viewport
+ // only when there is something to display there. The scale goes first to
+ // avoid offsetting our deferred position by scaling at the viewport center.
+ // All position and scale changes resulting from a web process event should
+ // go through here to be applied on the viewport to avoid showing incomplete
+ // tiles to the user during a few milliseconds.
+ if (m_effectiveScaleIsLocked) {
+ m_client->setContentsScale(m_effectiveScale, false);
+ m_effectiveScaleIsLocked = false;
+ }
+ if (m_viewportPosIsLocked) {
+ FloatPoint clampedPos = clampViewportToContents(m_viewportPos, m_effectiveScale);
+ // There might be rendered frames not covering our requested position yet, wait for it.
+ if (FloatRect(clampedPos, viewportSizeInContentsCoordinates()).intersects(coveredRect)) {
+ m_client->setViewportPosition(clampedPos);
+ m_viewportPosIsLocked = false;
+ }
+ }
+}
+
+void PageViewportController::pageTransitionViewportReady()
+{
+ if (!m_rawAttributes.layoutSize.isEmpty()) {
+ m_hadUserInteraction = false;
+ applyScaleAfterRenderingContents(innerBoundedViewportScale(toViewportScale(m_rawAttributes.initialScale)));
+ }
- m_client->didChangeContentsSize();
+ // At this point we should already have received the first viewport arguments and the requested scroll
+ // position for the newly loaded page and sent our reactions to the web process. It's now safe to tell
+ // the web process to start rendering the new page contents and possibly re-use the current tiles.
+ // This assumes that all messages have been handled in order and that nothing has been pushed back on the event loop.
+ m_webPageProxy->commitPageTransitionViewport();
}
void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition)
@@ -126,7 +173,12 @@ void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition)
if (m_activeDeferrerCount)
return;
- m_client->setViewportPosition(clampViewportToContents(cssPosition, m_effectiveScale));
+ FloatRect endVisibleContentRect(clampViewportToContents(cssPosition, m_effectiveScale), viewportSizeInContentsCoordinates());
+ if (m_lastFrameCoveredRect.intersects(endVisibleContentRect))
+ m_client->setViewportPosition(endVisibleContentRect.location());
+ else
+ // Keep the unclamped position in case the contents size is changed later on.
+ applyPositionAfterRenderingContents(cssPosition);
}
void PageViewportController::didChangeViewportSize(const FloatSize& newSize)
@@ -145,8 +197,11 @@ void PageViewportController::didChangeViewportSize(const FloatSize& newSize)
void PageViewportController::didChangeContentsVisibility(const FloatPoint& viewportPos, float viewportScale, const FloatPoint& trajectoryVector)
{
- m_viewportPos = viewportPos;
- m_effectiveScale = viewportScale;
+ if (!m_viewportPosIsLocked)
+ m_viewportPos = viewportPos;
+ if (!m_effectiveScaleIsLocked)
+ m_effectiveScale = viewportScale;
+
syncVisibleContents(trajectoryVector);
}
@@ -156,7 +211,7 @@ void PageViewportController::syncVisibleContents(const FloatPoint& trajectoryVec
if (!drawingArea || m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
return;
- FloatRect visibleContentsRect(clampViewportToContents(m_viewportPos, m_effectiveScale), m_viewportSize / m_effectiveScale);
+ FloatRect visibleContentsRect(clampViewportToContents(m_viewportPos, m_effectiveScale), viewportSizeInContentsCoordinates());
visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
drawingArea->setVisibleContentsRect(visibleContentsRect, m_effectiveScale, trajectoryVector);
@@ -177,6 +232,11 @@ void PageViewportController::didChangeViewportAttributes(const WebCore::Viewport
m_client->didChangeViewportAttributes();
}
+WebCore::FloatSize PageViewportController::viewportSizeInContentsCoordinates() const
+{
+ return WebCore::FloatSize(m_viewportSize.width() / m_effectiveScale, m_viewportSize.height() / m_effectiveScale);
+}
+
void PageViewportController::suspendContent()
{
if (m_hasSuspendedContent)
@@ -188,12 +248,6 @@ void PageViewportController::suspendContent()
void PageViewportController::resumeContent()
{
- if (!m_rawAttributes.layoutSize.isEmpty() && m_rawAttributes.initialScale > 0) {
- m_hadUserInteraction = false;
- m_client->setContentsScale(innerBoundedViewportScale(toViewportScale(m_rawAttributes.initialScale)), /* isInitialScale */ true);
- m_rawAttributes.initialScale = -1; // Mark used.
- }
-
m_client->didResumeContent();
if (!m_hasSuspendedContent)
@@ -203,15 +257,32 @@ void PageViewportController::resumeContent()
m_webPageProxy->resumeActiveDOMObjectsAndAnimations();
}
+void PageViewportController::applyScaleAfterRenderingContents(float scale)
+{
+ m_effectiveScale = scale;
+ m_effectiveScaleIsLocked = true;
+ syncVisibleContents();
+}
+
+void PageViewportController::applyPositionAfterRenderingContents(const FloatPoint& pos)
+{
+ m_viewportPos = pos;
+ m_viewportPosIsLocked = true;
+ syncVisibleContents();
+}
+
void PageViewportController::updateMinimumScaleToFit()
{
+ if (m_viewportSize.isEmpty())
+ return;
+
float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, WebCore::roundedIntSize(m_viewportSize), WebCore::roundedIntSize(m_contentsSize));
if (!fuzzyCompare(minimumScale, m_minimumScaleToFit, 0.001)) {
m_minimumScaleToFit = minimumScale;
if (!m_hadUserInteraction && !hasSuspendedContent())
- m_client->setContentsScale(toViewportScale(minimumScale), true /* isInitialScale */);
+ applyScaleAfterRenderingContents(toViewportScale(minimumScale));
m_client->didChangeViewportAttributes();
}