[Extra zoom mode] Add a mechanism to extend the height of the layout viewport in...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Apr 2018 21:00:50 +0000 (21:00 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 Apr 2018 21:00:50 +0000 (21:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184782
<rdar://problem/38346712>

Reviewed by Tim Horton.

Source/WebCore:

Add a new helper on FrameView to compute an expanded layout viewport size, as well as a new setting for the
height expansion factor when computing visual viewport dimensions. See WebKit/ChangeLog for more detail.

Test: fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html

* page/FrameView.cpp:
(WebCore::FrameView::expandedLayoutViewportSize):
* page/FrameView.h:
* page/Settings.yaml:

Source/WebKit:

In extra zoom mode, at initial scale, fixed position elements may take up a large portion of the viewport. This
leaves little room for non-fixed-position elements; to improve this experience, we introduce a mechanism to
extend the height of the layout viewport. By default, the layout viewport size is determined by the FrameView's
baseLayoutViewportSize, and passed into FrameView::computeUpdatedLayoutViewportRect in the client layer; in
extra zoom mode, if the layout viewport is shorter than the document width, we try to double the height of the
layout viewport and clamp to the document height if necessary.

* Shared/WebPreferences.yaml:

Add a new preference to determine the factor by which we should expand the height of the layout viewport. By
default, this is 0 (no increase in layout viewport height); in extra zoom mode, this is 1, which means we'll
increase the layout viewport's height by 1x the default height.

* Shared/WebPreferencesDefaultValues.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView activeMinimumLayoutSizes:]):

Fixes a bug when computing the active minimum layout size. If a minimum allowed layout width is specified, we
clamp the active layout width (normally the view size) so that it is no less than the minimum allowed layout
width. However, the height is currently unaffected, which causes FrameView::baseLayoutViewportSize to return a
bogus size, where the width is scaled to 320px but the height isn't. Instead, we should scale the layout height
to match the new width here.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::computeCustomFixedPositionRect const):

Expand the base viewport layout size if necessary, given the expansion factor in WebPreferences.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::updatePreferences):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::dynamicViewportSizeUpdate):

Expand the base viewport layout size if necessary, given the expansion factor in Settings.

LayoutTests:

Add a new layout test to exercise the following scenarios:
•   The layout viewport should be fully extended when the document is much taller than the viewport.
•   Programmatically shrinking the document height to less than the viewport height causes the layout viewport
    to shrink to the viewport height.
•   Programmatically extending the document height to a little more than the viewport height causes the layout
    viewport to also expand, but this time, only to the new document height.

* TestExpectations:

Skip tests in fast/visual-viewport/extrazoom by default.

* fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing-expected.txt: Added.
* fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230819 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing-expected.txt [new file with mode: 0644]
LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/Settings.yaml
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebPreferences.yaml
Source/WebKit/Shared/WebPreferencesDefaultValues.h
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index e6b97d9..ae37f7b 100644 (file)
@@ -1,3 +1,25 @@
+2018-04-19  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Extra zoom mode] Add a mechanism to extend the height of the layout viewport in extra zoom mode
+        https://bugs.webkit.org/show_bug.cgi?id=184782
+        <rdar://problem/38346712>
+
+        Reviewed by Tim Horton.
+
+        Add a new layout test to exercise the following scenarios:
+        •   The layout viewport should be fully extended when the document is much taller than the viewport.
+        •   Programmatically shrinking the document height to less than the viewport height causes the layout viewport
+            to shrink to the viewport height.
+        •   Programmatically extending the document height to a little more than the viewport height causes the layout
+            viewport to also expand, but this time, only to the new document height.
+
+        * TestExpectations:
+
+        Skip tests in fast/visual-viewport/extrazoom by default.
+
+        * fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing-expected.txt: Added.
+        * fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html: Added.
+
 2018-04-19  Chris Dumez  <cdumez@apple.com>
 
         REGRESSION (r229133): decidePolicyForNavigationAction not called for loading an HTML string
index ee36cab..97acb48 100644 (file)
@@ -18,6 +18,7 @@ editing/caret/ios [ Skip ]
 editing/pasteboard/gtk [ Skip ]
 editing/selection/ios [ Skip ]
 tiled-drawing [ Skip ]
+fast/visual-viewport/extrazoom [ Skip ]
 fast/visual-viewport/tiled-drawing [ Skip ]
 swipe [ Skip ]
 fast/zooming/ios [ Skip ]
diff --git a/LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing-expected.txt b/LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing-expected.txt
new file mode 100644 (file)
index 0000000..3125957
--- /dev/null
@@ -0,0 +1,62 @@
+
+Before scrolling.
+PASS topRectBeforeScrolling.top is 0
+PASS topRectBeforeScrolling.left is 0
+PASS topRectBeforeScrolling.width is innerWidth
+PASS topRectBeforeScrolling.height is 50
+PASS bottomRectBeforeScrolling.top is >= innerHeight
+PASS bottomRectBeforeScrolling.left is 0
+PASS bottomRectBeforeScrolling.width is innerWidth
+PASS bottomRectBeforeScrolling.height is 50
+PASS layoutViewportBeforeScrolling.top is 0
+PASS layoutViewportBeforeScrolling.left is 0
+PASS layoutViewportBeforeScrolling.width is innerWidth
+PASS layoutViewportBeforeScrolling.height is >= innerHeight
+
+After scrolling 2500px down.
+PASS 0 is >= topRectAfterScrolling.bottom
+PASS topRectAfterScrolling.left is 0
+PASS topRectAfterScrolling.width is innerWidth
+PASS topRectAfterScrolling.height is 50
+PASS bottomRectAfterScrolling.bottom is innerHeight
+PASS bottomRectAfterScrolling.left is 0
+PASS bottomRectAfterScrolling.width is innerWidth
+PASS bottomRectAfterScrolling.height is 50
+PASS layoutViewportAfterScrolling.bottom is 2500 + innerHeight
+PASS layoutViewportAfterScrolling.left is 0
+PASS layoutViewportAfterScrolling.width is innerWidth
+PASS layoutViewportAfterScrolling.height is >= innerHeight
+
+After shortening document height to 100px.
+PASS topRectAfterShorteningBody.top is 0
+PASS topRectAfterShorteningBody.left is 0
+PASS topRectAfterShorteningBody.width is innerWidth
+PASS topRectAfterShorteningBody.height is 50
+PASS bottomRectAfterShorteningBody.bottom is innerHeight
+PASS bottomRectAfterShorteningBody.left is 0
+PASS bottomRectAfterShorteningBody.width is innerWidth
+PASS bottomRectAfterShorteningBody.height is 50
+PASS layoutViewportAfterShorteningBody.top is 0
+PASS layoutViewportAfterShorteningBody.left is 0
+PASS layoutViewportAfterShorteningBody.width is innerWidth
+PASS layoutViewportAfterShorteningBody.height is innerHeight
+
+After extending document height to 1.5x innerHeight.
+PASS topRectAfterExtendingBody.top is 0
+PASS topRectAfterExtendingBody.left is 0
+PASS topRectAfterExtendingBody.width is innerWidth
+PASS topRectAfterExtendingBody.height is 50
+PASS bottomRectAfterExtendingBody.top is >= innerHeight
+PASS bottomRectAfterExtendingBody.left is 0
+PASS bottomRectAfterExtendingBody.width is innerWidth
+PASS bottomRectAfterExtendingBody.height is 50
+PASS layoutViewportAfterExtendingBody.top is 0
+PASS layoutViewportAfterExtendingBody.left is 0
+PASS layoutViewportAfterExtendingBody.width is innerWidth
+PASS layoutViewportAfterExtendingBody.height is >= innerHeight
+PASS layoutViewportAfterExtendingBody.height < layoutViewportBeforeScrolling.height is true
+PASS finalDocumentHeight is layoutViewportAfterExtendingBody.height
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html b/LayoutTests/fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html
new file mode 100644 (file)
index 0000000..30da981
--- /dev/null
@@ -0,0 +1,139 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<meta name="viewport" content="width=device-width">
+<head>
+    <script src="../../../resources/js-test.js"></script>
+    <script src="../../../resources/ui-helper.js"></script>
+    <style>
+        body, html {
+            margin: 0;
+            width: 100%;
+        }
+
+        body {
+            height: 5000px;
+        }
+
+        .fixed {
+            width: 100%;
+            height: 50px;
+            background-color: green;
+            position: fixed;
+            left: 0;
+        }
+
+        #top {
+            top: 0;
+            background-color: green;
+        }
+
+        #bottom {
+            bottom: 0;
+            background-color: blue;
+        }
+    </style>
+    <script>
+        async function runTest() {
+            jsTestIsAsync = true;
+
+            // FIXME: This works around innerWidth and innerHeight being incorrect (i.e. unadjusted for shrink-to-fit
+            // behavior) in the load event listener of the body. See: https://bugs.webkit.org/show_bug.cgi?id=184788.
+            await UIHelper.ensurePresentationUpdate();
+
+            topRectBeforeScrolling = document.getElementById("top").getBoundingClientRect();
+            bottomRectBeforeScrolling = document.getElementById("bottom").getBoundingClientRect();
+            layoutViewportBeforeScrolling = internals.layoutViewportRect();
+
+            const verticalScrollAmount = 2500;
+            scrollBy(0, verticalScrollAmount);
+
+            topRectAfterScrolling = document.getElementById("top").getBoundingClientRect();
+            bottomRectAfterScrolling = document.getElementById("bottom").getBoundingClientRect();
+            layoutViewportAfterScrolling = internals.layoutViewportRect();
+
+            document.body.style.height = "100px";
+            await UIHelper.ensurePresentationUpdate();
+
+            topRectAfterShorteningBody = document.getElementById("top").getBoundingClientRect();
+            bottomRectAfterShorteningBody = document.getElementById("bottom").getBoundingClientRect();
+            layoutViewportAfterShorteningBody = internals.layoutViewportRect();
+
+            finalDocumentHeight = Math.round(innerHeight * 1.5);
+            document.body.style.height = `${finalDocumentHeight}px`;
+            await UIHelper.ensurePresentationUpdate();
+
+            topRectAfterExtendingBody = document.getElementById("top").getBoundingClientRect();
+            bottomRectAfterExtendingBody = document.getElementById("bottom").getBoundingClientRect();
+            layoutViewportAfterExtendingBody = internals.layoutViewportRect();
+
+            debug("\nBefore scrolling.")
+            shouldBe("topRectBeforeScrolling.top", "0");
+            shouldBe("topRectBeforeScrolling.left", "0");
+            shouldBe("topRectBeforeScrolling.width", "innerWidth");
+            shouldBe("topRectBeforeScrolling.height", "50");
+            shouldBeGreaterThanOrEqual("bottomRectBeforeScrolling.top", "innerHeight");
+            shouldBe("bottomRectBeforeScrolling.left", "0");
+            shouldBe("bottomRectBeforeScrolling.width", "innerWidth");
+            shouldBe("bottomRectBeforeScrolling.height", "50");
+            shouldBe("layoutViewportBeforeScrolling.top", "0");
+            shouldBe("layoutViewportBeforeScrolling.left", "0");
+            shouldBe("layoutViewportBeforeScrolling.width", "innerWidth");
+            shouldBeGreaterThanOrEqual("layoutViewportBeforeScrolling.height", "innerHeight");
+
+            debug(`\nAfter scrolling ${verticalScrollAmount}px down.`);
+            shouldBeGreaterThanOrEqual("0", "topRectAfterScrolling.bottom");
+            shouldBe("topRectAfterScrolling.left", "0");
+            shouldBe("topRectAfterScrolling.width", "innerWidth");
+            shouldBe("topRectAfterScrolling.height", "50");
+            shouldBe("bottomRectAfterScrolling.bottom", "innerHeight");
+            shouldBe("bottomRectAfterScrolling.left", "0");
+            shouldBe("bottomRectAfterScrolling.width", "innerWidth");
+            shouldBe("bottomRectAfterScrolling.height", "50");
+            shouldBe("layoutViewportAfterScrolling.bottom", `${verticalScrollAmount} + innerHeight`);
+            shouldBe("layoutViewportAfterScrolling.left", "0");
+            shouldBe("layoutViewportAfterScrolling.width", "innerWidth");
+            shouldBeGreaterThanOrEqual("layoutViewportAfterScrolling.height", "innerHeight");
+
+            debug("\nAfter shortening document height to 100px.");
+            shouldBe("topRectAfterShorteningBody.top", "0");
+            shouldBe("topRectAfterShorteningBody.left", "0");
+            shouldBe("topRectAfterShorteningBody.width", "innerWidth");
+            shouldBe("topRectAfterShorteningBody.height", "50");
+            shouldBe("bottomRectAfterShorteningBody.bottom", "innerHeight");
+            shouldBe("bottomRectAfterShorteningBody.left", "0");
+            shouldBe("bottomRectAfterShorteningBody.width", "innerWidth");
+            shouldBe("bottomRectAfterShorteningBody.height", "50");
+            shouldBe("layoutViewportAfterShorteningBody.top", "0");
+            shouldBe("layoutViewportAfterShorteningBody.left", "0");
+            shouldBe("layoutViewportAfterShorteningBody.width", "innerWidth");
+            shouldBe("layoutViewportAfterShorteningBody.height", "innerHeight");
+
+            debug("\nAfter extending document height to 1.5x innerHeight.")
+            shouldBe("topRectAfterExtendingBody.top", "0");
+            shouldBe("topRectAfterExtendingBody.left", "0");
+            shouldBe("topRectAfterExtendingBody.width", "innerWidth");
+            shouldBe("topRectAfterExtendingBody.height", "50");
+            shouldBeGreaterThanOrEqual("bottomRectAfterExtendingBody.top", "innerHeight");
+            shouldBe("bottomRectAfterExtendingBody.left", "0");
+            shouldBe("bottomRectAfterExtendingBody.width", "innerWidth");
+            shouldBe("bottomRectAfterExtendingBody.height", "50");
+            shouldBe("layoutViewportAfterExtendingBody.top", "0");
+            shouldBe("layoutViewportAfterExtendingBody.left", "0");
+            shouldBe("layoutViewportAfterExtendingBody.width", "innerWidth");
+            shouldBeGreaterThanOrEqual("layoutViewportAfterExtendingBody.height", "innerHeight");
+
+            // The layout viewport should not be expanded past document bounds. Before scrolling, the document height
+            // was much taller than the window height, but afterwards, the document height is short enough that we
+            // should clamp the extended layout viewport to its bounds.
+            shouldBeTrue("layoutViewportAfterExtendingBody.height < layoutViewportBeforeScrolling.height");
+            shouldBe("finalDocumentHeight", "layoutViewportAfterExtendingBody.height");
+
+            finishJSTest();
+        }
+    </script>
+</head>
+<body onload="runTest()">
+    <div class="fixed" id="top"></div>
+    <div class="fixed" id="bottom"></div>
+</body>
+</html>
index ae89cf2..0e6611a 100644 (file)
@@ -1,3 +1,21 @@
+2018-04-19  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Extra zoom mode] Add a mechanism to extend the height of the layout viewport in extra zoom mode
+        https://bugs.webkit.org/show_bug.cgi?id=184782
+        <rdar://problem/38346712>
+
+        Reviewed by Tim Horton.
+
+        Add a new helper on FrameView to compute an expanded layout viewport size, as well as a new setting for the
+        height expansion factor when computing visual viewport dimensions. See WebKit/ChangeLog for more detail.
+
+        Test: fast/visual-viewport/extrazoom/layout-viewport-after-scrolling-and-resizing.html
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::expandedLayoutViewportSize):
+        * page/FrameView.h:
+        * page/Settings.yaml:
+
 2018-04-19  Chris Dumez  <cdumez@apple.com>
 
         REGRESSION (r229133): decidePolicyForNavigationAction not called for loading an HTML string
index 773bb79..662f64c 100644 (file)
@@ -1529,6 +1529,19 @@ void FrameView::removeViewportConstrainedObject(RenderElement* object)
     }
 }
 
+LayoutSize FrameView::expandedLayoutViewportSize(const LayoutSize& baseLayoutViewportSize, const LayoutSize& documentSize, double heightExpansionFactor)
+{
+    if (!heightExpansionFactor)
+        return baseLayoutViewportSize;
+
+    auto documentHeight = documentSize.height();
+    auto layoutViewportHeight = baseLayoutViewportSize.height();
+    if (layoutViewportHeight > documentHeight)
+        return baseLayoutViewportSize;
+
+    return { baseLayoutViewportSize.width(), std::min<LayoutUnit>(documentHeight, (1 + heightExpansionFactor) * layoutViewportHeight) };
+}
+
 LayoutRect FrameView::computeUpdatedLayoutViewportRect(const LayoutRect& layoutViewport, const LayoutRect& documentRect, const LayoutSize& unobscuredContentSize, const LayoutRect& unobscuredContentRect, const LayoutSize& baseLayoutViewportSize, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, LayoutViewportConstraint constraint)
 {
     LayoutRect layoutViewportRect = layoutViewport;
index 276db68..3d1b57e 100644 (file)
@@ -302,6 +302,8 @@ public:
     // Static function can be called from another thread.
     static LayoutPoint scrollPositionForFixedPosition(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements, int headerHeight, int footerHeight);
 
+    WEBCORE_EXPORT static LayoutSize expandedLayoutViewportSize(const LayoutSize& baseLayoutViewportSize, const LayoutSize& documentSize, double heightExpansionFactor);
+
     enum class LayoutViewportConstraint { ConstrainedToDocumentRect, Unconstrained };
     WEBCORE_EXPORT static LayoutRect computeUpdatedLayoutViewportRect(const LayoutRect& layoutViewport, const LayoutRect& documentRect, const LayoutSize& unobscuredContentSize, const LayoutRect& unobscuredContentRect, const LayoutSize& baseLayoutViewportSize, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, LayoutViewportConstraint);
     
index 70dde49..a06f689 100644 (file)
@@ -529,6 +529,11 @@ treatIPAddressAsDomain:
 mediaPreloadingEnabled:
   initial: false
 
+layoutViewportHeightExpansionFactor:
+  type: double
+  initial: 0
+  onChange: setNeedsRecalcStyleInAllFrames
+
 # Runtime-enabled features
 visualViewportEnabled:
   initial: false
index 50542da..3b8b693 100644 (file)
@@ -1,3 +1,46 @@
+2018-04-19  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Extra zoom mode] Add a mechanism to extend the height of the layout viewport in extra zoom mode
+        https://bugs.webkit.org/show_bug.cgi?id=184782
+        <rdar://problem/38346712>
+
+        Reviewed by Tim Horton.
+
+        In extra zoom mode, at initial scale, fixed position elements may take up a large portion of the viewport. This
+        leaves little room for non-fixed-position elements; to improve this experience, we introduce a mechanism to
+        extend the height of the layout viewport. By default, the layout viewport size is determined by the FrameView's
+        baseLayoutViewportSize, and passed into FrameView::computeUpdatedLayoutViewportRect in the client layer; in
+        extra zoom mode, if the layout viewport is shorter than the document width, we try to double the height of the
+        layout viewport and clamp to the document height if necessary.
+
+        * Shared/WebPreferences.yaml:
+
+        Add a new preference to determine the factor by which we should expand the height of the layout viewport. By
+        default, this is 0 (no increase in layout viewport height); in extra zoom mode, this is 1, which means we'll
+        increase the layout viewport's height by 1x the default height.
+
+        * Shared/WebPreferencesDefaultValues.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView activeMinimumLayoutSizes:]):
+
+        Fixes a bug when computing the active minimum layout size. If a minimum allowed layout width is specified, we
+        clamp the active layout width (normally the view size) so that it is no less than the minimum allowed layout
+        width. However, the height is currently unaffected, which causes FrameView::baseLayoutViewportSize to return a
+        bogus size, where the width is scaled to 320px but the height isn't. Instead, we should scale the layout height
+        to match the new width here.
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::computeCustomFixedPositionRect const):
+
+        Expand the base viewport layout size if necessary, given the expansion factor in WebPreferences.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::updatePreferences):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::dynamicViewportSizeUpdate):
+
+        Expand the base viewport layout size if necessary, given the expansion factor in Settings.
+
 2018-04-19  Brian Burg  <bburg@apple.com>
 
         Web Automation: simulated mouse interactions should not be done until associated DOM events have been dispatched
index 520f7f1..7611a36 100644 (file)
@@ -638,6 +638,10 @@ VisualViewportEnabled:
   type: bool
   defaultValue: true
 
+LayoutViewportHeightExpansionFactor:
+  type: double
+  defaultValue: DEFAULT_VISUAL_VIEWPORT_HEIGHT_EXPANSION_FACTOR
+
 NeedsStorageAccessFromFileURLsQuirk:
   type: bool
   defaultValue: true
index 566289a..e75f3d4 100644 (file)
 #define DEFAULT_AVFOUNDATION_ENABLED false
 #endif
 
+#if ENABLE(EXTRA_ZOOM_MODE)
+#define DEFAULT_VISUAL_VIEWPORT_HEIGHT_EXPANSION_FACTOR 1
+#else
+#define DEFAULT_VISUAL_VIEWPORT_HEIGHT_EXPANSION_FACTOR 0
+#endif
+
 // Cocoa ports must disable experimental features on release branches for now.
 #if ENABLE(EXPERIMENTAL_FEATURES) || PLATFORM(COCOA)
 #define DEFAULT_EXPERIMENTAL_FEATURES_ENABLED true
index b41f264..859bffb 100644 (file)
@@ -2596,7 +2596,8 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     sizes.viewSize = WebCore::FloatSize { bounds.size };
 #endif
 
-    sizes.minimumLayoutSize = { std::max<float>(sizes.viewSize.width(), self._minimumAllowedLayoutWidth), sizes.viewSize.height() };
+    auto layoutWidth = std::max<float>(sizes.viewSize.width(), self._minimumAllowedLayoutWidth);
+    sizes.minimumLayoutSize = { layoutWidth, sizes.viewSize.height() * (layoutWidth / sizes.viewSize.width()) };
     return sizes;
 }
 
index 392498f..49e7c43 100644 (file)
@@ -274,10 +274,11 @@ WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect&
     if (!visualViewportEnabled)
         return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
         
-    FloatSize constainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
+    FloatSize constrainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
     FloatRect unobscuredContentRectForViewport = isBelowMinimumScale ? constrainedUnobscuredRect : unobscuredContentRectRespectingInputViewBounds;
 
-    FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constainedSize), LayoutRect(unobscuredContentRectForViewport), m_baseLayoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
+    auto layoutViewportSize = FrameView::expandedLayoutViewportSize(m_baseLayoutViewportSize, LayoutSize(documentRect.size()), m_preferences->layoutViewportHeightExpansionFactor());
+    FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constrainedSize), LayoutRect(unobscuredContentRectForViewport), layoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
     
     if (layoutViewportRect != currentCustomFixedPositionRect)
         LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
index 5a09db2..9070b2e 100644 (file)
@@ -3192,6 +3192,8 @@ void WebPage::updatePreferences(const WebPreferencesStore& store)
     }
 #endif
 
+    settings.setLayoutViewportHeightExpansionFactor(store.getDoubleValueForKey(WebPreferencesKey::layoutViewportHeightExpansionFactorKey()));
+
     if (m_drawingArea)
         m_drawingArea->updatePreferences(store);
 }
index 11cee2d..9f7f49f 100644 (file)
@@ -2649,9 +2649,11 @@ void WebPage::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, cons
 
     frameView.updateLayoutAndStyleIfNeededRecursive();
 
-    if (frameView.frame().settings().visualViewportEnabled()) {
+    auto& settings = frameView.frame().settings();
+    if (settings.visualViewportEnabled()) {
         LayoutRect documentRect = IntRect(frameView.scrollOrigin(), frameView.contentsSize());
-        LayoutRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(frameView.layoutViewportRect(), documentRect, LayoutSize(newUnobscuredContentRect.size()), LayoutRect(newUnobscuredContentRect), frameView.baseLayoutViewportSize(), frameView.minStableLayoutViewportOrigin(), frameView.maxStableLayoutViewportOrigin(), FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect);
+        auto layoutViewportSize = FrameView::expandedLayoutViewportSize(frameView.baseLayoutViewportSize(), LayoutSize(documentRect.size()), settings.layoutViewportHeightExpansionFactor());
+        LayoutRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(frameView.layoutViewportRect(), documentRect, LayoutSize(newUnobscuredContentRect.size()), LayoutRect(newUnobscuredContentRect), layoutViewportSize, frameView.minStableLayoutViewportOrigin(), frameView.maxStableLayoutViewportOrigin(), FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect);
         frameView.setLayoutViewportOverrideRect(layoutViewportRect);
     } else {
         IntRect fixedPositionLayoutRect = enclosingIntRect(frameView.viewportConstrainedObjectsRect());