[Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Feb 2018 17:16:31 +0000 (17:16 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Feb 2018 17:16:31 +0000 (17:16 +0000)
commit58b0b71fd538930f77a1b1807ad9e7cd7a4d6211
treee16f82532f1fca08ab7ba938b603c8f736413d93
parent7a18075ca7454afb7249573143ceb47926ee5dd8
[Extra zoom mode] Implement additional SPI for adjusting viewport shrink-to-fit behavior
https://bugs.webkit.org/show_bug.cgi?id=183100
<rdar://problem/37840987>

Reviewed by Tim Horton.

Source/WebCore:

Introduce new customization options to ViewportConfiguration. The first is m_forceHorizontalShrinkToFit, which
(when set to true) forces the viewport to scale using shrink-to-fit heuristics, regardless of whether
"shrink-to-fit=no" is specified via viewport parameters or if content width did not exceed minimum layout size.
The second is m_viewSize, which reflects the true size of the viewport. See WebKit ChangeLog for more details.

Tests: ViewportSizingTests.ForceShrinkToFitViewportOverridesViewportParameters
       ViewportSizingTests.ShrinkToFitViewportWithMinimumAllowedLayoutWidth

* page/ViewportConfiguration.cpp:
(WebCore::ViewportConfiguration::ViewportConfiguration):
(WebCore::ViewportConfiguration::setMinimumLayoutSize):

Plumb the real size of the view alongside the minimum layout size when updating the minimum layout size.

(WebCore::ViewportConfiguration::setForceHorizontalShrinkToFit):
(WebCore::ViewportConfiguration::shouldIgnoreHorizontalScalingConstraints const):

Bail early and return true if forceHorizontalShrinkToFit is set. This forces shrink-to-fit even in cases where
"shrink-to-fit" is set to "no", or content dimensions don't exceed layout dimensions.

(WebCore::ViewportConfiguration::initialScaleFromSize const):

Use view dimensions rather than minimum layout dimensions when computing the initial scale. Minimum layout size
is no longer always equal to the size of the view if the client has specified a minimum allowed layout width. As
such, when computing the initial scale, to ensure that the content (which was laid out using the minimum layout
size) fits within the real viewport, we need to divide real viewport dimensions by content dimensions.

(WebCore::ViewportConfiguration::minimumScale const):

Similarly, use view size instead of minimum layout size to compute minimum scale.

(WebCore::ViewportConfiguration::description const):
* page/ViewportConfiguration.h:

Source/WebKit:

Add new SPI hooks to provide finer control over certain aspects of the shrink-to-fit viewport heuristic.
Currently, in certain cases of iPad multitasking, Safari allows shrinking content to fit by default. This means
that even when "width=device-width" is used, if the contents of the page are too wide to fit within the
viewport's width, we'll adjust the initial scale such that the viewport can fit all of the content.

However, in certain viewport dimensions, this heuristic is insufficient to ensure that pages are laid out and
displayed properly within the viewport. Namely, one could imagine that an element with a hard-coded width that
is larger than the real viewport width would cause all other elements with dimensions relative to the body to be
excessively shrunk down once shrink-to-fit is applied, so the page would still look broken even if the contents
of the page all fit within the viewport.

To mitigate this, we decouple the notions of minimum layout size from the size of the actual viewport (which we
simply refer to as "view size"). This allows us to introduce a mechanism where we lay out the page at a given
minimum layout size that is larger than the size of the view; later, when we determine the initial scale, we
then apply shrink-to-fit scaling using the view size rather than the minimum layout size. This grants us the
ability to lay out content as if our view were large, but still ensure that the contents of the page fit within
the actual view.

* Shared/VisibleContentRectUpdateInfo.cpp:
(WebKit::VisibleContentRectUpdateInfo::encode const):
(WebKit::VisibleContentRectUpdateInfo::decode):
(WebKit::operator<<):
* Shared/VisibleContentRectUpdateInfo.h:
(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::forceHorizontalShrinkToFit const):
(WebKit::operator==):

Plumb the forceHorizontalShrinkToFit flag through VisibleContentRectUpdateInfo.

* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:

Plumb viewSize through IPC to WebPage.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):

Start off WKWebView flags at their initial values.

(-[WKWebView _minimumAllowedLayoutWidth]):
(-[WKWebView _setMinimumAllowedLayoutWidth:]):

This provides the minimum width at which the page will lay out, such that if the view width dips below this
value, we'll use this minimum allowed layout width instead. 0 by default.

(-[WKWebView activeMinimumLayoutSizes:]):

Refactor this from a static function to a helper method on WKWebView that computes both the minimum layout size
(which takes minimum allowed layout width into account) as well as the real view size. Refactor all call sites
to use this new method, and also propagate the view size down via IPC, alongside the minimum layout size.

(-[WKWebView _dispatchSetMinimumLayoutSize:viewSize:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _setForceHorizontalViewportShrinkToFit:]):
(-[WKWebView _forceHorizontalViewportShrinkToFit]):

Setting this flag to YES forces us to always shrink-to-fit in the horizontal axis. NO by default.

(-[WKWebView _beginAnimatedResizeWithUpdates:]):
(-[WKWebView _endAnimatedResize]):
(activeMinimumLayoutSize): Deleted.

More refactoring to replace activeMinimumLayoutSize() with -activeMinimumLayoutSizes:.

(-[WKWebView _dispatchSetMinimumLayoutSize:]): Deleted.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInsets:unobscuredSafeAreaInsets:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):

Pass _forceHorizontalViewportShrinkToFit into the visible content rect update.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::dynamicViewportSizeUpdate):
(WebKit::WebPageProxy::setViewportConfigurationMinimumLayoutSize):

Plumb viewSize alongside the existing minimumLayoutSize.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_credentialsMessenger):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::setViewportConfigurationMinimumLayoutSize):
(WebKit::WebPage::dynamicViewportSizeUpdate):
(WebKit::WebPage::updateVisibleContentRects):

Set forceHorizontalShrinkToFit on the viewport configuration here.

Tools:

Add API tests that exercise -_setMinimumAllowedLayoutWidth: and -_setForceHorizontalViewportShrinkToFit:. See
WebKit ChangeLog for more detail.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/ViewportSizingTests.mm: Added.
(TestWebKitAPI::while):
(viewportTestPageMarkup):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@229063 268f45cc-cd09-0410-ab3c-d52691b4dbfc
21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/ViewportConfiguration.cpp
Source/WebCore/page/ViewportConfiguration.h
Source/WebKit/ChangeLog
Source/WebKit/Shared/VisibleContentRectUpdateInfo.cpp
Source/WebKit/Shared/VisibleContentRectUpdateInfo.h
Source/WebKit/Shared/WebPageCreationParameters.cpp
Source/WebKit/Shared/WebPageCreationParameters.h
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WKContentView.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/ios/ViewportSizingTests.mm [new file with mode: 0644]