Title: [167614] trunk/Source/WebKit2
Revision
167614
Author
[email protected]
Date
2014-04-21 13:10:12 -0700 (Mon, 21 Apr 2014)

Log Message

[iOS][WK2] Make dynamic viewport size update content aware
https://bugs.webkit.org/show_bug.cgi?id=131874

Patch by Benjamin Poulain <[email protected]> on 2014-04-21
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):

Modified Paths

Diff

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()));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to