Modified: trunk/Source/WebKit2/ChangeLog (167613 => 167614)
--- trunk/Source/WebKit2/ChangeLog 2014-04-21 19:53:55 UTC (rev 167613)
+++ trunk/Source/WebKit2/ChangeLog 2014-04-21 20:10:12 UTC (rev 167614)
@@ -1,3 +1,28 @@
+2014-04-21 Benjamin Poulain <[email protected]>
+
+ [iOS][WK2] Make dynamic viewport size update content aware
+ https://bugs.webkit.org/show_bug.cgi?id=131874
+
+ Reviewed by Tim Horton.
+
+ When possible, adjust the scroll position based on the content on dynamic viewport resize.
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::WebPage):
+ (WebKit::WebPage::scalePage):
+ (WebKit::WebPage::pageDidScroll):
+ * WebProcess/WebPage/WebPage.h:
+ The scrolling heuristic are not invertible, especially the content heuristic. To have the right
+ behavior when doing resize without changing the page, we save the old scroll position and restore
+ it when the content size and scale is restored.
+
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::dynamicViewportSizeUpdate):
+ On dynamic update, start by finding what node is at the center of the screen. After the layout, put that
+ node back in the center.
+
+ (WebKit::WebPage::updateVisibleContentRects):
+
2014-04-21 Anders Carlsson <[email protected]>
Need default WKNavigationDelegate behavior
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (167613 => 167614)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2014-04-21 19:53:55 UTC (rev 167613)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp 2014-04-21 20:10:12 UTC (rev 167614)
@@ -288,6 +288,7 @@
, m_userHasChangedPageScaleFactor(false)
, m_screenSize(parameters.screenSize)
, m_availableScreenSize(parameters.availableScreenSize)
+ , m_inDynamicSizeUpdate(false)
#endif
, m_inspectorClient(0)
, m_backgroundColor(Color::white)
@@ -1286,6 +1287,8 @@
return;
#if PLATFORM(IOS)
+ if (!m_inDynamicSizeUpdate)
+ m_dynamicSizeUpdateHistory.clear();
m_scaleWasSetByUIProcess = false;
#endif
PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
@@ -1620,6 +1623,10 @@
void WebPage::pageDidScroll()
{
+#if PLATFORM(IOS)
+ if (!m_inDynamicSizeUpdate)
+ m_dynamicSizeUpdateHistory.clear();
+#endif
m_uiClient->pageDidScroll(this);
send(Messages::WebPageProxy::PageDidScroll());
Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (167613 => 167614)
--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2014-04-21 19:53:55 UTC (rev 167613)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h 2014-04-21 20:10:12 UTC (rev 167614)
@@ -50,6 +50,7 @@
#include <WebCore/Editor.h>
#include <WebCore/FrameLoaderTypes.h>
#include <WebCore/IntRect.h>
+#include <WebCore/IntSizeHash.h>
#include <WebCore/Page.h>
#include <WebCore/PageVisibilityState.h>
#include <WebCore/ScrollTypes.h>
@@ -1159,6 +1160,8 @@
WebCore::FloatSize m_screenSize;
WebCore::FloatSize m_availableScreenSize;
WebCore::IntSize m_blockSelectionDesiredSize;
+ bool m_inDynamicSizeUpdate;
+ HashMap<std::pair<WebCore::IntSize, double>, WebCore::IntPoint> m_dynamicSizeUpdateHistory;
#endif
WebInspectorClient* m_inspectorClient;
Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (167613 => 167614)
--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm 2014-04-21 19:53:55 UTC (rev 167613)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm 2014-04-21 20:10:12 UTC (rev 167614)
@@ -75,12 +75,14 @@
#import <WebCore/PlatformMouseEvent.h>
#import <WebCore/RenderBlock.h>
#import <WebCore/RenderImage.h>
+#import <WebCore/RenderView.h>
#import <WebCore/ResourceBuffer.h>
#import <WebCore/SharedBuffer.h>
#import <WebCore/TextIterator.h>
#import <WebCore/VisibleUnits.h>
#import <WebCore/WKContentObservation.h>
#import <WebCore/WebEvent.h>
+#import <wtf/TemporaryChange.h>
using namespace WebCore;
@@ -1764,12 +1766,40 @@
void WebPage::dynamicViewportSizeUpdate(const IntSize& minimumLayoutSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, double targetScale)
{
+ TemporaryChange<bool> dynamicSizeUpdateGuard(m_inDynamicSizeUpdate, true);
// FIXME: this does not handle the cases where the content would change the content size or scroll position from _javascript_.
// To handle those cases, we would need to redo this computation on every change until the next visible content rect update.
FrameView& frameView = *m_page->mainFrame().view();
IntSize oldContentSize = frameView.contentsSize();
+ float oldPageScaleFactor = m_page->pageScaleFactor();
+ m_dynamicSizeUpdateHistory.add(std::make_pair(oldContentSize, oldPageScaleFactor), IntPoint(frameView.scrollOffset()));
+
+ RefPtr<Node> oldNodeAtCenter;
+ float relativeHorizontalPositionInNodeAtCenter = 0;
+ float relativeVerticalPositionInNodeAtCenter = 0;
+ {
+ IntRect unobscuredContentRect = frameView.unobscuredContentRect();
+ IntPoint unobscuredContentRectCenter = unobscuredContentRect.center();
+
+ HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
+ HitTestResult hitTestResult = HitTestResult(unobscuredContentRectCenter);
+
+ RenderView* mainFrameRenderView = frameView.renderView();
+ mainFrameRenderView->hitTest(request, hitTestResult);
+
+ if (Node* node = hitTestResult.innerNode()) {
+ if (RenderObject* renderer = node->renderer()) {
+ FrameView& containingView = *node->document().frame()->view();
+ FloatRect boundingBox = containingView.contentsToRootView(renderer->absoluteBoundingBoxRect(true));
+ relativeHorizontalPositionInNodeAtCenter = (unobscuredContentRectCenter.x() - boundingBox.x()) / boundingBox.width();
+ relativeVerticalPositionInNodeAtCenter = (unobscuredContentRectCenter.y() - boundingBox.y()) / boundingBox.height();
+ oldNodeAtCenter = node;
+ }
+ }
+ }
+
m_viewportConfiguration.setMinimumLayoutSize(minimumLayoutSize);
IntSize newLayoutSize = m_viewportConfiguration.layoutSize();
setFixedLayoutSize(newLayoutSize);
@@ -1807,21 +1837,34 @@
newUnobscuredRectY - obscuredTopMargin,
newUnobscuredRectWidth + obscuredLeftMargin + obscuredRightMargin,
newUnobscuredRectHeight + obscuredTopMargin + obscuredBottomMargin);
-
- // FIXME: Adjust the rects based on the content.
}
if (oldContentSize != newContentSize || scale != targetScale) {
// Snap the new unobscured rect back into the content rect.
- newUnobscuredContentRect.setWidth(std::min(static_cast<float>(newContentSize.width()), newExposedContentRect.width()));
- newUnobscuredContentRect.setHeight(std::min(static_cast<float>(newContentSize.height()), newExposedContentRect.height()));
+ newUnobscuredContentRect.setWidth(std::min(static_cast<float>(newContentSize.width()), newUnobscuredContentRect.width()));
+ newUnobscuredContentRect.setHeight(std::min(static_cast<float>(newContentSize.height()), newUnobscuredContentRect.height()));
- if (oldContentSize != newContentSize) {
- // If the content size has changed, keep the same relative position.
- FloatPoint oldContentCenter = targetUnobscuredRect.center();
- float relativeHorizontalPosition = oldContentCenter.x() / oldContentSize.width();
- float relativeVerticalPosition = oldContentCenter.y() / oldContentSize.height();
- FloatPoint newRelativeContentCenter(relativeHorizontalPosition * newContentSize.width(), relativeVerticalPosition * newContentSize.height());
+ const auto& previousPosition = m_dynamicSizeUpdateHistory.find(std::pair<IntSize, float>(newContentSize, scale));
+ if (previousPosition != m_dynamicSizeUpdateHistory.end()) {
+ IntPoint restoredPosition = previousPosition->value;
+ FloatPoint deltaPosition(restoredPosition.x() - newUnobscuredContentRect.x(), restoredPosition.y() - newUnobscuredContentRect.y());
+ newUnobscuredContentRect.moveBy(deltaPosition);
+ newExposedContentRect.moveBy(deltaPosition);
+ } else if (oldContentSize != newContentSize) {
+ FloatPoint newRelativeContentCenter;
+
+ if (RenderObject* renderer = oldNodeAtCenter ? oldNodeAtCenter->renderer() : nullptr) {
+ FrameView& containingView = *oldNodeAtCenter->document().frame()->view();
+ FloatRect newBoundingBox = containingView.contentsToRootView(renderer->absoluteBoundingBoxRect(true));
+ newRelativeContentCenter = FloatPoint(newBoundingBox.x() + relativeHorizontalPositionInNodeAtCenter * newBoundingBox.width(), newBoundingBox.y() + relativeVerticalPositionInNodeAtCenter * newBoundingBox.height());
+ } else {
+ // If the content size has changed, keep the same relative position.
+ FloatPoint oldContentCenter = targetUnobscuredRect.center();
+ float relativeHorizontalPosition = oldContentCenter.x() / oldContentSize.width();
+ float relativeVerticalPosition = oldContentCenter.y() / oldContentSize.height();
+ newRelativeContentCenter = FloatPoint(relativeHorizontalPosition * newContentSize.width(), relativeVerticalPosition * newContentSize.height());
+ }
+
FloatPoint newUnobscuredContentRectCenter = newUnobscuredContentRect.center();
FloatPoint positionDelta(newRelativeContentCenter.x() - newUnobscuredContentRectCenter.x(), newRelativeContentCenter.y() - newUnobscuredContentRectCenter.y());
newUnobscuredContentRect.moveBy(positionDelta);
@@ -1863,10 +1906,10 @@
m_drawingArea->setExposedContentRect(newExposedContentRect);
if (scale == targetScale)
- scalePage(scale, frameView.scrollPosition());
+ scalePage(scale, roundedUnobscuredContentRect.location());
if (scale != targetScale || roundedIntPoint(targetUnobscuredRect.location()) != roundedUnobscuredContentRect.location())
- send(Messages::WebPageProxy::DynamicViewportUpdateChangedTarget(scale, frameView.scrollPosition()));
+ send(Messages::WebPageProxy::DynamicViewportUpdateChangedTarget(scale, roundedUnobscuredContentRect.location()));
}
void WebPage::viewportConfigurationChanged()
@@ -1957,21 +2000,27 @@
if (floatBoundedScale != m_page->pageScaleFactor()) {
m_scaleWasSetByUIProcess = true;
+ m_dynamicSizeUpdateHistory.clear();
+
m_page->setPageScaleFactor(floatBoundedScale, scrollPosition);
- if (m_drawingArea->layerTreeHost())
- m_drawingArea->layerTreeHost()->deviceOrPageScaleFactorChanged();
+ if (LayerTreeHost* layerTreeHost = m_drawingArea->layerTreeHost())
+ layerTreeHost->deviceOrPageScaleFactorChanged();
send(Messages::WebPageProxy::PageScaleFactorDidChange(floatBoundedScale));
}
- m_page->mainFrame().view()->setScrollOffset(scrollPosition);
- m_page->mainFrame().view()->setUnobscuredContentRect(roundedUnobscuredRect);
+ FrameView& frameView = *m_page->mainFrame().view();
+ if (scrollPosition != IntPoint(frameView.scrollOffset()))
+ m_dynamicSizeUpdateHistory.clear();
+ frameView.setScrollOffset(scrollPosition);
+ frameView.setUnobscuredContentRect(roundedUnobscuredRect);
+
double horizontalVelocity = visibleContentRectUpdateInfo.horizontalVelocity();
double verticalVelocity = visibleContentRectUpdateInfo.verticalVelocity();
double scaleChangeRate = visibleContentRectUpdateInfo.scaleChangeRate();
adjustVelocityDataForBoundedScale(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.scale(), boundedScale);
- m_page->mainFrame().view()->setScrollVelocity(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.timestamp());
+ frameView.setScrollVelocity(horizontalVelocity, verticalVelocity, scaleChangeRate, visibleContentRectUpdateInfo.timestamp());
if (visibleContentRectUpdateInfo.inStableState())
m_page->mainFrame().view()->setCustomFixedPositionLayoutRect(enclosingIntRect(visibleContentRectUpdateInfo.customFixedPositionRect()));