[iOS WK2] Implement support for visual viewports
https://bugs.webkit.org/show_bug.cgi?id=164765

Reviewed by Tim Horton.

Adopt the visual viewport scrolling model in iOS WK2.
Source/WebCore:

This is more complex than the Mac implementation for two primary reasons. First,
WKWebView needs to to able to control the rectangle used for fixed position layout
to get the correct behavior when zooming all the way out, and because iOS displays
pages scaled down, exposing document overflow such that the layout viewport rectangle
has to get larger than the initial containing block size (which does not happen on Mac).

This is achieved by pushing a "layoutViewportOverrideRect" down onto FrameView, in
a similar way to the customFixedPositionRect that's used now. We share that name
for now in code that is agnostic to its use (e.g. VisibleContentRectUpdateInfo).

I tried so hard to write tests, but ran into various problems (webkit.org/b/164762,
webkit.org/b/164764). Will add tests via webkit.org/b/164764.

* page/FrameView.cpp:
(WebCore::FrameView::fixedScrollableAreaBoundsInflatedForScrolling): layoutViewportOrigin()
was removed.
(WebCore::FrameView::setBaseLayoutViewportOrigin): Rename with "base" to make it clearer that
it can be overridden.
(WebCore::FrameView::setLayoutViewportOverrideRect):
(WebCore::FrameView::baseLayoutViewportSize): Renamed.
(WebCore::FrameView::updateLayoutViewport): Logging.
(WebCore::FrameView::layoutViewportRect):
(WebCore::FrameView::scrollPositionForFixedPosition):
(WebCore::FrameView::unscaledMaximumScrollPosition): During page transitions on iOS, it
was possible for unscaledDocumentRect to be empty, but visibleSize() to be non-empty, leading
to odd negative max scroll offsets, so clamp to 0,0.
(WebCore::FrameView::setLayoutViewportOrigin): Deleted.
* page/FrameView.h:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::reconcileScrollingState): scrollPositionForFixedPosition() already does the
visualViewportEnabled() check.
* page/scrolling/mac/ScrollingTreeFixedNode.mm:
(WebCore::ScrollingTreeFixedNode::updateLayersAfterAncestorChange):
* platform/graphics/FloatSize.cpp:
(WebCore::FloatSize::constrainedBetween): Added for consistency with the other geometry types.
* platform/graphics/FloatSize.h:
* platform/graphics/LayoutSize.cpp:
(WebCore::LayoutSize::constrainedBetween): Ditto.
* platform/graphics/LayoutSize.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::clientLogicalWidthForFixedPosition): If we have an override layout viewport, its size might be different
from the RenderView's size (the initial containing block), so we need to use the layoutViewportRect here.
(WebCore::RenderView::clientLogicalHeightForFixedPosition):

Source/WebKit2:

Pass the parameters used for computing the layout viewport up to WK2 via RemoteLayerTreeTransaction.
These are stored on WebPageProxy. When they change, _didCommitLayerTree triggers a -_updateVisibleContentRects.

WebPageProxy::computeCustomFixedPositionRect() is the function that computes the "override" layout viewport.
It starts with the baseLayoutViewportSize from the web process (which is based on the initial containing block
size), then ensures that it's no smaller than the unobscured content rect, since it makes no sense for the
layout viewport to be smaller than the visual viewport. The static FrameView::computeLayoutViewportOrigin()
is then use to "push" the layout viewport around as the visual viewport changes.

* Shared/VisibleContentRectUpdateInfo.h:
* Shared/WebCoreArgumentCoders.cpp: Encode LayoutSize and LayoutPoint.
(IPC::ArgumentCoder<LayoutSize>::encode):
(IPC::ArgumentCoder<LayoutSize>::decode):
(IPC::ArgumentCoder<LayoutPoint>::encode):
(IPC::ArgumentCoder<LayoutPoint>::decode):
* Shared/WebCoreArgumentCoders.h:
* Shared/mac/RemoteLayerTreeTransaction.h:
(WebKit::RemoteLayerTreeTransaction::baseLayoutViewportSize):
(WebKit::RemoteLayerTreeTransaction::setBaseLayoutViewportSize):
(WebKit::RemoteLayerTreeTransaction::minStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::setMinStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::maxStableLayoutViewportOrigin):
(WebKit::RemoteLayerTreeTransaction::setMaxStableLayoutViewportOrigin):
* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTransaction::encode):
(WebKit::RemoteLayerTreeTransaction::decode):
(WebKit::RemoteLayerTreeTransaction::description):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:]):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
(WebKit::RemoteScrollingCoordinatorProxy::visualViewportEnabled): Accessor.
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::customFixedPositionRect):
* UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::customFixedPositionRect):
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
(-[WKContentView _didCommitLayerTree:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::computeCustomFixedPositionRect): When visual viewports are enabled, compute
the layout viewport rect, taking the baseLayoutViewportSize and the current unobscured rect into account.
(WebKit::WebPageProxy::updateLayoutViewportParameters):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
* WebProcess/WebPage/WebPage.cpp: Encode in the transaction the layout viewport parameters (with minor refactor).
(WebKit::WebPage::willCommitLayerTree):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::updateVisibleContentRects): This is where the web process receives the new override layout viewport
from the web process (with some logging).

LayoutTests:

These tests don't correctly test iOS WK2's async scrolling behavior (webkit.org/b/164779)
so rebaseline.

* platform/ios-simulator-wk2/fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/rtl-nonzoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/rtl-zoomed-rects-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
* platform/ios-simulator-wk2/fast/visual-viewport/zoomed-rects-expected.txt: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@208748 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp b/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
index 4457692..4c286a1 100644
--- a/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
+++ b/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
@@ -352,7 +352,7 @@
     WTF::switchOn(layoutViewportOriginOrOverrideRect,
         [&frameView](Optional<FloatPoint> origin) {
             if (origin)
-                frameView.setLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
+                frameView.setBaseLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
         }, [&frameView](Optional<FloatRect> overrideRect) {
 #if PLATFORM(IOS)
             if (overrideRect)
@@ -383,7 +383,7 @@
     GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
 
     ASSERT(frameView.scrollPosition() == roundedIntPoint(scrollPosition));
-    LayoutPoint scrollPositionForFixed = visualViewportEnabled() ? frameView.layoutViewportOrigin() : frameView.scrollPositionForFixedPosition();
+    LayoutPoint scrollPositionForFixed = frameView.scrollPositionForFixedPosition();
     float topContentInset = frameView.topContentInset();
 
     FloatPoint positionForInsetClipLayer;