Changeset 208213 in webkit


Ignore:
Timestamp:
Oct 31, 2016, 10:32:35 PM (9 years ago)
Author:
Simon Fraser
Message:

Add basic visual/layout viewport support for fixed position layout
https://bugs.webkit.org/show_bug.cgi?id=164261

Reviewed by Dean Jackson.

Source/WebCore:

This patch adds a new behavior for position:fixed objects on zooming. Instead of
interpolating between two implicit viewports as we do now, have explicit and distinct
layout and visual viewports.

The layout viewport is always the size of the initial containing block (i.e. the RenderView).
Position:fixed and sticky elements are laid out relative to the layout viewport.

The visual viewport is the visible part of the view, in content coordinates.

When the user pans and zooms, the visual viewport changes. If it hits the edge of the
layout viepwort, it pushes the layout viewport in that direction; it's as if the user
is dragging the layout viewport around.

The layout viewport is maintained on FrameView, and has to be recomputed when the
scroll position changes, when the view size changes, and when the content size (which
affets min/max scroll position) changes. Layout viewport size and position are computed
in unzoomed coordinates, requiring some new functions on FrameView to return these.

Updated the TileCoverageMap to show the layout viewport visually.

Subsequent patches will plumb the layout and visual viewports through the scrolling tree.

Tests: fast/visual-viewport/nonzoomed-rects.html

fast/visual-viewport/zoomed-fixed-scroll-down-then-up.html
fast/visual-viewport/zoomed-fixed.html
fast/visual-viewport/zoomed-rects.html

  • page/FrameView.cpp:

(WebCore::FrameView::fixedScrollableAreaBoundsInflatedForScrolling):
(WebCore::FrameView::scrollPositionRespectingCustomFixedPosition):
(WebCore::FrameView::computeLayoutViewportOrigin):
(WebCore::FrameView::setLayoutViewportOrigin):
(WebCore::FrameView::updateLayoutViewport):
(WebCore::FrameView::minStableLayoutViewportOrigin):
(WebCore::FrameView::maxStableLayoutViewportOrigin):
(WebCore::FrameView::layoutViewportRect):
(WebCore::FrameView::visualViewportRect):
(WebCore::FrameView::viewportConstrainedVisibleContentRect):
(WebCore::FrameView::rectForFixedPositionLayout):
(WebCore::FrameView::scrollPositionForFixedPosition):
(WebCore::FrameView::unscaledMinimumScrollPosition):
(WebCore::FrameView::unscaledMaximumScrollPosition):
(WebCore::FrameView::scrollPositionChanged):
(WebCore::FrameView::availableContentSizeChanged):
(WebCore::FrameView::performPostLayoutTasks):
(WebCore::FrameView::scrollTo):
(WebCore::FrameView::useCustomFixedPositionLayoutRect):

  • page/FrameView.h:
  • page/Settings.in:
  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):

  • platform/graphics/TiledBacking.h:
  • platform/graphics/ca/TileController.cpp:

(WebCore::TileController::setLayoutViewportRect):

  • platform/graphics/ca/TileController.h:
  • platform/graphics/ca/TileCoverageMap.cpp:

(WebCore::TileCoverageMap::TileCoverageMap):
(WebCore::TileCoverageMap::update):

  • platform/graphics/ca/TileCoverageMap.h:
  • rendering/RenderBoxModelObject.cpp:

(WebCore::RenderBoxModelObject::constrainingRectForStickyPosition):

  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateCompositedBounds):

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::requiresCompositingForPosition):
(WebCore::RenderLayerCompositor::computeFixedViewportConstraints):

  • rendering/RenderTreeAsText.cpp:

(WebCore::externalRepresentation): Logging here is useful when debugging tests.

  • testing/Internals.cpp:

(WebCore::Internals::layoutViewportRect): Expose these rects so tests can dump them.
(WebCore::Internals::visualViewportRect):

  • testing/Internals.h:
  • testing/Internals.idl:

Source/WebKit2:

Don't make visualViewportEnabled an experimental feature, because I don't want it enabled
by default in WebKitTestRunner (and therefore mismatching DumpRenderTree).

  • Shared/WebPreferencesDefinitions.h:

Tools:

Don't give tests in the "visual-viewport" directory a flexible viewport.

  • DumpRenderTree/mac/DumpRenderTree.mm:

(shouldMakeViewportFlexible):

  • WebKitTestRunner/TestOptions.cpp:

(WTR::shouldMakeViewportFlexible):

LayoutTests:

  • fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
  • fast/visual-viewport/nonzoomed-rects.html: Added.
  • fast/visual-viewport/zoomed-fixed-expected.txt: Added.
  • fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
  • fast/visual-viewport/zoomed-fixed-scroll-down-then-up.html: Added.
  • fast/visual-viewport/zoomed-fixed.html: Added.
  • fast/visual-viewport/zoomed-rects-expected.txt: Added.
  • fast/visual-viewport/zoomed-rects.html: Added.
  • platform/ios-simulator/fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
  • platform/ios-simulator/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
  • platform/ios-simulator/fast/visual-viewport/zoomed-rects-expected.txt: Added.
  • resources/js-test-pre.js:

(evalAndLog):
(evalAndLogResult):
(shouldEvaluateTo):

Location:
trunk
Files:
14 added
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208209 r208213  
     12016-10-31  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add basic visual/layout viewport support for fixed position layout
     4        https://bugs.webkit.org/show_bug.cgi?id=164261
     5
     6        Reviewed by Dean Jackson.
     7
     8        * fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
     9        * fast/visual-viewport/nonzoomed-rects.html: Added.
     10        * fast/visual-viewport/zoomed-fixed-expected.txt: Added.
     11        * fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
     12        * fast/visual-viewport/zoomed-fixed-scroll-down-then-up.html: Added.
     13        * fast/visual-viewport/zoomed-fixed.html: Added.
     14        * fast/visual-viewport/zoomed-rects-expected.txt: Added.
     15        * fast/visual-viewport/zoomed-rects.html: Added.
     16        * platform/ios-simulator/fast/visual-viewport/nonzoomed-rects-expected.txt: Added.
     17        * platform/ios-simulator/fast/visual-viewport/zoomed-fixed-scroll-down-then-up-expected.txt: Added.
     18        * platform/ios-simulator/fast/visual-viewport/zoomed-rects-expected.txt: Added.
     19        * resources/js-test-pre.js:
     20        (evalAndLog):
     21        (evalAndLogResult):
     22        (shouldEvaluateTo):
     23
    1242016-10-29  Filip Pizlo  <fpizlo@apple.com>
    225
  • trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-responsetype-sync-request-expected.txt

    r203333 r208213  
    1 CONSOLE MESSAGE: line 600: XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.
    2 CONSOLE MESSAGE: line 600: XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.
     1CONSOLE MESSAGE: line 616: XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.
     2CONSOLE MESSAGE: line 616: XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.
    33This tests that the XMLHttpRequest responseType attribute is not modifiable for synchronous HTTP(S) requests.
    44
  • trunk/LayoutTests/http/tests/websocket/tests/hybi/binary-type-expected.txt

    r203333 r208213  
    1 CONSOLE MESSAGE: line 600: 'Blob' is not a valid value for binaryType; binaryType remains unchanged.
    2 CONSOLE MESSAGE: line 600: 'ArrayBuffer' is not a valid value for binaryType; binaryType remains unchanged.
    3 CONSOLE MESSAGE: line 600: '' is not a valid value for binaryType; binaryType remains unchanged.
     1CONSOLE MESSAGE: line 616: 'Blob' is not a valid value for binaryType; binaryType remains unchanged.
     2CONSOLE MESSAGE: line 616: 'ArrayBuffer' is not a valid value for binaryType; binaryType remains unchanged.
     3CONSOLE MESSAGE: line 616: '' is not a valid value for binaryType; binaryType remains unchanged.
    44Test WebSocket.binaryType attribute.
    55
  • trunk/LayoutTests/resources/js-test-pre.js

    r207809 r208213  
    194194{
    195195  if (typeof _a != "string")
    196     debug("WARN: tryAndLog() expects a string argument");
     196    debug("WARN: evalAndLog() expects a string argument");
    197197
    198198  // Log first in case things go horribly wrong or this causes a sync event.
     
    207207  }
    208208  return _av;
     209}
     210
     211function evalAndLogResult(_a)
     212{
     213  if (typeof _a != "string")
     214    debug("WARN: evalAndLogResult() expects a string argument");
     215
     216  var _av;
     217  try {
     218     _av = eval(_a);
     219  } catch (e) {
     220    testFailed(_a + " threw exception " + e);
     221  }
     222
     223  debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
    209224}
    210225
     
    446461function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ""); }
    447462
    448 function shouldEvaluateTo(actual, expected) {
     463function shouldEvaluateTo(actual, expected)
     464{
    449465  // A general-purpose comparator.  'actual' should be a string to be
    450466  // evaluated, as for shouldBe(). 'expected' may be any type and will be
  • trunk/Source/WebCore/ChangeLog

    r208212 r208213  
     12016-10-31  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add basic visual/layout viewport support for fixed position layout
     4        https://bugs.webkit.org/show_bug.cgi?id=164261
     5
     6        Reviewed by Dean Jackson.
     7
     8        This patch adds a new behavior for position:fixed objects on zooming. Instead of
     9        interpolating between two implicit viewports as we do now, have explicit and distinct
     10        layout and visual viewports.
     11
     12        The layout viewport is always the size of the initial containing block (i.e. the RenderView).
     13        Position:fixed and sticky elements are laid out relative to the layout viewport.
     14
     15        The visual viewport is the visible part of the view, in content coordinates.
     16
     17        When the user pans and zooms, the visual viewport changes. If it hits the edge of the
     18        layout viepwort, it pushes the layout viewport in that direction; it's as if the user
     19        is dragging the layout viewport around.
     20
     21        The layout viewport is maintained on FrameView, and has to be recomputed when the
     22        scroll position changes, when the view size changes, and when the content size (which
     23        affets min/max scroll position) changes. Layout viewport size and position are computed
     24        in unzoomed coordinates, requiring some new functions on FrameView to return these.
     25
     26        Updated the TileCoverageMap to show the layout viewport visually.
     27
     28        Subsequent patches will plumb the layout and visual viewports through the scrolling tree.
     29
     30        Tests: fast/visual-viewport/nonzoomed-rects.html
     31               fast/visual-viewport/zoomed-fixed-scroll-down-then-up.html
     32               fast/visual-viewport/zoomed-fixed.html
     33               fast/visual-viewport/zoomed-rects.html
     34
     35        * page/FrameView.cpp:
     36        (WebCore::FrameView::fixedScrollableAreaBoundsInflatedForScrolling):
     37        (WebCore::FrameView::scrollPositionRespectingCustomFixedPosition):
     38        (WebCore::FrameView::computeLayoutViewportOrigin):
     39        (WebCore::FrameView::setLayoutViewportOrigin):
     40        (WebCore::FrameView::updateLayoutViewport):
     41        (WebCore::FrameView::minStableLayoutViewportOrigin):
     42        (WebCore::FrameView::maxStableLayoutViewportOrigin):
     43        (WebCore::FrameView::layoutViewportRect):
     44        (WebCore::FrameView::visualViewportRect):
     45        (WebCore::FrameView::viewportConstrainedVisibleContentRect):
     46        (WebCore::FrameView::rectForFixedPositionLayout):
     47        (WebCore::FrameView::scrollPositionForFixedPosition):
     48        (WebCore::FrameView::unscaledMinimumScrollPosition):
     49        (WebCore::FrameView::unscaledMaximumScrollPosition):
     50        (WebCore::FrameView::scrollPositionChanged):
     51        (WebCore::FrameView::availableContentSizeChanged):
     52        (WebCore::FrameView::performPostLayoutTasks):
     53        (WebCore::FrameView::scrollTo):
     54        (WebCore::FrameView::useCustomFixedPositionLayoutRect):
     55        * page/FrameView.h:
     56        * page/Settings.in:
     57        * page/scrolling/AsyncScrollingCoordinator.cpp:
     58        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
     59        * platform/graphics/TiledBacking.h:
     60        * platform/graphics/ca/TileController.cpp:
     61        (WebCore::TileController::setLayoutViewportRect):
     62        * platform/graphics/ca/TileController.h:
     63        * platform/graphics/ca/TileCoverageMap.cpp:
     64        (WebCore::TileCoverageMap::TileCoverageMap):
     65        (WebCore::TileCoverageMap::update):
     66        * platform/graphics/ca/TileCoverageMap.h:
     67        * rendering/RenderBoxModelObject.cpp:
     68        (WebCore::RenderBoxModelObject::constrainingRectForStickyPosition):
     69        * rendering/RenderLayerBacking.cpp:
     70        (WebCore::RenderLayerBacking::updateCompositedBounds):
     71        * rendering/RenderLayerCompositor.cpp:
     72        (WebCore::RenderLayerCompositor::requiresCompositingForPosition):
     73        (WebCore::RenderLayerCompositor::computeFixedViewportConstraints):
     74        * rendering/RenderTreeAsText.cpp:
     75        (WebCore::externalRepresentation): Logging here is useful when debugging tests.
     76        * testing/Internals.cpp:
     77        (WebCore::Internals::layoutViewportRect): Expose these rects so tests can dump them.
     78        (WebCore::Internals::visualViewportRect):
     79        * testing/Internals.h:
     80        * testing/Internals.idl:
     81
    1822016-10-31  Simon Fraser  <simon.fraser@apple.com>
    283
  • trunk/Source/WebCore/page/FrameView.cpp

    r208003 r208213  
    10921092LayoutRect FrameView::fixedScrollableAreaBoundsInflatedForScrolling(const LayoutRect& uninflatedBounds) const
    10931093{
    1094     LayoutPoint scrollPosition = scrollPositionRespectingCustomFixedPosition();
    1095 
    1096     LayoutSize topLeftExpansion = scrollPosition - minimumScrollPosition();
    1097     LayoutSize bottomRightExpansion = maximumScrollPosition() - scrollPosition;
     1094    LayoutPoint scrollPosition;
     1095    LayoutSize topLeftExpansion;
     1096    LayoutSize bottomRightExpansion;
     1097
     1098    if (frame().settings().visualViewportEnabled()) {
     1099        // FIXME: this is wrong under zooming; uninflatedBounds is scaled but the scroll positions are not.
     1100        scrollPosition = layoutViewportOrigin();
     1101        topLeftExpansion = scrollPosition - unscaledMinimumScrollPosition();
     1102        bottomRightExpansion = unscaledMaximumScrollPosition() - scrollPosition;
     1103    } else {
     1104        scrollPosition = scrollPositionRespectingCustomFixedPosition();
     1105        topLeftExpansion = scrollPosition - minimumScrollPosition();
     1106        bottomRightExpansion = maximumScrollPosition() - scrollPosition;
     1107    }
    10981108
    10991109    return LayoutRect(uninflatedBounds.location() - topLeftExpansion, uninflatedBounds.size() + topLeftExpansion + bottomRightExpansion);
     
    11031113{
    11041114#if PLATFORM(IOS)
    1105     return useCustomFixedPositionLayoutRect() ? customFixedPositionLayoutRect().location() : scrollPosition();
    1106 #else
     1115    if (!frame().settings().visualViewportEnabled())
     1116        return useCustomFixedPositionLayoutRect() ? customFixedPositionLayoutRect().location() : scrollPosition();
     1117#endif
     1118
    11071119    return scrollPositionForFixedPosition();
    1108 #endif
    11091120}
    11101121
     
    17821793}
    17831794
     1795LayoutPoint FrameView::computeLayoutViewportOrigin(const LayoutRect& visualViewport, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, const LayoutRect& layoutViewport)
     1796{
     1797    LayoutPoint layoutViewportOrigin = layoutViewport.location();
     1798
     1799    if (visualViewport.x() < layoutViewport.x() || visualViewport.x() < stableLayoutViewportOriginMin.x())
     1800        layoutViewportOrigin.setX(visualViewport.x());
     1801
     1802    if (visualViewport.y() < layoutViewport.y() || visualViewport.y() < stableLayoutViewportOriginMin.y())
     1803        layoutViewportOrigin.setY(visualViewport.y());
     1804
     1805    if (visualViewport.maxX() > layoutViewport.maxX() || (visualViewport.maxX() - layoutViewport.width()) > stableLayoutViewportOriginMax.x())
     1806        layoutViewportOrigin.setX(visualViewport.maxX() - layoutViewport.width());
     1807
     1808    if (visualViewport.maxY() > layoutViewport.maxY() || (visualViewport.maxY() - layoutViewport.height()) > stableLayoutViewportOriginMax.y())
     1809        layoutViewportOrigin.setY(visualViewport.maxY() - layoutViewport.height());
     1810
     1811    return layoutViewportOrigin;
     1812}
     1813
     1814void FrameView::setLayoutViewportOrigin(LayoutPoint origin)
     1815{
     1816    ASSERT(frame().settings().visualViewportEnabled());
     1817
     1818    if (origin == m_layoutViewportOrigin)
     1819        return;
     1820
     1821    m_layoutViewportOrigin = origin;
     1822    setViewportConstrainedObjectsNeedLayout();
     1823   
     1824    if (TiledBacking* tiledBacking = this->tiledBacking())
     1825        tiledBacking->setLayoutViewportRect(FloatRect(layoutViewportRect()));
     1826}
     1827
     1828void FrameView::updateLayoutViewport()
     1829{
     1830    if (!frame().settings().visualViewportEnabled())
     1831        return;
     1832
     1833    LayoutRect layoutViewport = layoutViewportRect();
     1834
     1835    LOG_WITH_STREAM(Scrolling, stream << "\nFrameView " << this << " updateLayoutViewport()");
     1836    LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
     1837    LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewportRect());
     1838    LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << unscaledMinimumScrollPosition() << " max: "<< unscaledMaximumScrollPosition());
     1839
     1840    LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport);
     1841    if (newLayoutViewportOrigin != layoutViewportOrigin()) {
     1842        LOG_WITH_STREAM(Scrolling, stream << "layoutViewport changed to " << layoutViewport);
     1843        setLayoutViewportOrigin(newLayoutViewportOrigin);
     1844    }
     1845}
     1846
     1847LayoutPoint FrameView::minStableLayoutViewportOrigin() const
     1848{
     1849    return unscaledMinimumScrollPosition();
     1850}
     1851
     1852LayoutPoint FrameView::maxStableLayoutViewportOrigin() const
     1853{
     1854    return unscaledMaximumScrollPosition();
     1855}
     1856
     1857// Size of initial containing block, anchored at scroll position, in document coordinates (unchanged by scale factor).
     1858LayoutRect FrameView::layoutViewportRect() const
     1859{
     1860    return LayoutRect(m_layoutViewportOrigin, renderView() ? renderView()->size() : size());
     1861}
     1862
     1863LayoutRect FrameView::visualViewportRect() const
     1864{
     1865    // This isn't visibleContentRect(), because that uses a scaled scroll origin. Confused? Me too.
     1866    FloatRect visibleContentRect = this->visibleContentRect(LegacyIOSDocumentVisibleRect);
     1867    visibleContentRect.scale(1 / frameScaleFactor());
     1868    return LayoutRect(visibleContentRect);
     1869}
     1870
    17841871LayoutRect FrameView::viewportConstrainedVisibleContentRect() const
    17851872{
     1873    ASSERT(!frame().settings().visualViewportEnabled());
     1874
    17861875#if PLATFORM(IOS)
    17871876    if (useCustomFixedPositionLayoutRect())
     
    17941883}
    17951884
     1885LayoutRect FrameView::rectForFixedPositionLayout() const
     1886{
     1887    if (frame().settings().visualViewportEnabled())
     1888        return layoutViewportRect();
     1889
     1890    return viewportConstrainedVisibleContentRect();
     1891}
     1892
    17961893float FrameView::frameScaleFactor() const
    17971894{
    17981895    return frame().frameScaleFactor();
     1896}
     1897
     1898LayoutPoint FrameView::scrollPositionForFixedPosition() const
     1899{
     1900    if (frame().settings().visualViewportEnabled())
     1901        return layoutViewportOrigin();
     1902
     1903    return scrollPositionForFixedPosition(visibleContentRect(), totalContentsSize(), scrollPosition(), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), scrollBehaviorForFixedElements(), headerHeight(), footerHeight());
    17991904}
    18001905
     
    19282033   
    19292034    return maximumPosition;
     2035}
     2036
     2037ScrollPosition FrameView::unscaledMinimumScrollPosition() const
     2038{
     2039    if (RenderView* renderView = this->renderView()) {
     2040        IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
     2041
     2042        IntPoint unscaledScrollOrigin = -unscaledDocumentRect.location();
     2043        ScrollPosition minimumPosition = scrollPositionFromOffset(ScrollOffset(), toIntSize(unscaledScrollOrigin));
     2044
     2045        if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
     2046            minimumPosition.setY(unscaledMaximumScrollPosition().y());
     2047
     2048        return minimumPosition;
     2049    }
     2050   
     2051    return minimumScrollPosition();
     2052}
     2053
     2054ScrollPosition FrameView::unscaledMaximumScrollPosition() const
     2055{
     2056    if (RenderView* renderView = this->renderView()) {
     2057        IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
     2058        unscaledDocumentRect.expand(0, headerHeight() + footerHeight());
     2059       
     2060        // Max scroll position is size - visible - scrollOrigin, which is max - visible.
     2061        ScrollOffset maximumOffset = unscaledDocumentRect.maxXMaxYCorner() - visibleSize();
     2062        IntPoint unscaledScrollOrigin = -unscaledDocumentRect.location();
     2063        ScrollPosition maximumPosition = scrollPositionFromOffset(maximumOffset, toIntSize(unscaledScrollOrigin));
     2064
     2065        if (frame().isMainFrame() && m_scrollPinningBehavior == PinToTop)
     2066            maximumPosition.setY(unscaledMinimumScrollPosition().y());
     2067
     2068        return maximumPosition;
     2069    }
     2070
     2071    return maximumScrollPosition();
    19302072}
    19312073
     
    22752417    }
    22762418
     2419    LOG_WITH_STREAM(Scrolling, stream << "FrameView " << this << " scrollPositionChanged from " << oldPosition << " to " << newPosition);
     2420    updateLayoutViewport();
    22772421    viewportContentsChanged();
    22782422}
     
    24812625        document->updateViewportUnitsOnResize();
    24822626
     2627    updateLayoutViewport();
    24832628    setNeedsLayout();
    24842629    ScrollView::availableContentSizeChanged(reason);
     
    32633408
    32643409    sendResizeEventIfNeeded();
     3410   
     3411    updateLayoutViewport();
    32653412    viewportContentsChanged();
    32663413
     
    36013748    if (oldPosition != scrollPosition())
    36023749        scrollPositionChanged(oldPosition, scrollPosition());
     3750
    36033751    didChangeScrollOffset();
    36043752}
     
    47594907    return nullptr;
    47604908}
    4761    
     4909
    47624910#if PLATFORM(IOS)
     4911bool FrameView::useCustomFixedPositionLayoutRect() const
     4912{
     4913    return !frame().settings().visualViewportEnabled() && m_useCustomFixedPositionLayoutRect;
     4914}
     4915
    47634916void FrameView::setCustomFixedPositionLayoutRect(const IntRect& rect)
    47644917{
  • trunk/Source/WebCore/page/FrameView.h

    r207814 r208213  
    136136
    137137#if PLATFORM(IOS)
    138     bool useCustomFixedPositionLayoutRect() const { return m_useCustomFixedPositionLayoutRect; }
     138    bool useCustomFixedPositionLayoutRect() const;
    139139    IntRect customFixedPositionLayoutRect() const { return m_customFixedPositionLayoutRect; }
    140140    WEBCORE_EXPORT void setCustomFixedPositionLayoutRect(const IntRect&);
     
    246246    WEBCORE_EXPORT ScrollPosition maximumScrollPosition() const override;
    247247
    248     void viewportContentsChanged();
    249     WEBCORE_EXPORT void resumeVisibleImageAnimationsIncludingSubframes();
     248    // The scrollOrigin, scrollPosition, minimumScrollPosition and maximumScrollPosition are all affected by frame scale,
     249    // but layoutViewport computations require unscaled scroll positions.
     250    ScrollPosition unscaledMinimumScrollPosition() const;
     251    ScrollPosition unscaledMaximumScrollPosition() const;
     252
     253    void setLayoutViewportOrigin(LayoutPoint);
     254    LayoutPoint layoutViewportOrigin() const { return m_layoutViewportOrigin; }
     255   
     256    LayoutPoint minStableLayoutViewportOrigin() const;
     257    LayoutPoint maxStableLayoutViewportOrigin() const;
     258
     259    // These are in document coordinates, unaffected by zooming.
     260    WEBCORE_EXPORT LayoutRect layoutViewportRect() const;
     261    WEBCORE_EXPORT LayoutRect visualViewportRect() const;
    250262
    251263    // This is different than visibleContentRect() in that it ignores negative (or overly positive)
    252264    // offsets from rubber-banding, and it takes zooming into account.
    253265    LayoutRect viewportConstrainedVisibleContentRect() const;
     266   
     267    LayoutRect rectForFixedPositionLayout() const;
     268
     269    void viewportContentsChanged();
     270    WEBCORE_EXPORT void resumeVisibleImageAnimationsIncludingSubframes();
    254271
    255272    String mediaType() const;
     
    277294    // Functions for querying the current scrolled position, negating the effects of overhang
    278295    // and adjusting for page scale.
    279     LayoutPoint scrollPositionForFixedPosition() const
    280     {
    281         return scrollPositionForFixedPosition(visibleContentRect(), totalContentsSize(), scrollPosition(), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), scrollBehaviorForFixedElements(), headerHeight(), footerHeight());
    282     }
     296    LayoutPoint scrollPositionForFixedPosition() const;
    283297   
    284298    // Static function can be called from another thread.
    285299    static LayoutPoint scrollPositionForFixedPosition(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements, int headerHeight, int footerHeight);
     300
     301    static LayoutPoint computeLayoutViewportOrigin(const LayoutRect& visualViewport, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, const LayoutRect& layoutViewport);
    286302
    287303    // These layers are positioned differently when there is a topContentInset, a header, or a footer. These value need to be computed
     
    492508#endif
    493509
     510    // This function "smears" the "position:fixed" uninflatedBounds for scrolling, returning a rect that is the union of
     511    // all possible locations of the given rect under page scrolling.
    494512    LayoutRect fixedScrollableAreaBoundsInflatedForScrolling(const LayoutRect& uninflatedBounds) const;
     513
    495514    LayoutPoint scrollPositionRespectingCustomFixedPosition() const;
    496515
     
    661680
    662681    void updateScrollableAreaSet();
     682    void updateLayoutViewport();
    663683
    664684    void notifyPageThatContentAreaWillPaint() const override;
     
    759779
    760780    Optional<FloatRect> m_viewExposedRect;
     781   
     782    LayoutPoint m_layoutViewportOrigin;
    761783
    762784    unsigned m_deferSetNeedsLayoutCount;
  • trunk/Source/WebCore/page/Settings.in

    r208181 r208213  
    278278
    279279# Runtime-enabled features
    280 visualViewportEnabled initial=false
     280visualViewportEnabled initial=false, setNeedsStyleRecalcInAllFrames=1
    281281intersectionObserverEnabled initial=false
    282282
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r205818 r208213  
    359359                    footerLayer->syncPosition(positionForFooterLayer);
    360360
    361                 LayoutRect viewportRect = frameView.viewportConstrainedVisibleContentRect();
     361                LayoutRect viewportRect = frameView.rectForFixedPositionLayout();
    362362                syncChildPositions(viewportRect);
    363363            }
  • trunk/Source/WebCore/platform/graphics/TiledBacking.h

    r198189 r208213  
    2626#ifndef TiledBacking_h
    2727#define TiledBacking_h
     28
     29#include <wtf/Optional.h>
    2830
    2931namespace WebCore {
     
    7274    virtual void setVisibleRect(const FloatRect&) = 0;
    7375    virtual FloatRect visibleRect() const = 0;
     76
     77    // Only used to update the tile coverage map.
     78    virtual void setLayoutViewportRect(Optional<FloatRect>) = 0;
    7479
    7580    virtual void setCoverageRect(const FloatRect&) = 0;
  • trunk/Source/WebCore/platform/graphics/ca/TileController.cpp

    r206830 r208213  
    191191}
    192192
     193void TileController::setLayoutViewportRect(Optional<FloatRect> rect)
     194{
     195    if (rect == m_layoutViewportRect)
     196        return;
     197
     198    m_layoutViewportRect = rect;
     199    updateTileCoverageMap();
     200}
     201
    193202void TileController::setCoverageRect(const FloatRect& rect)
    194203{
  • trunk/Source/WebCore/platform/graphics/ca/TileController.h

    r206538 r208213  
    8383    FloatRect visibleRect() const override { return m_visibleRect; }
    8484    FloatRect coverageRect() const override { return m_coverageRect; }
     85    Optional<FloatRect> layoutViewportRect() const { return m_layoutViewportRect; }
    8586
    8687    unsigned blankPixelCount() const;
     
    141142    // TiledBacking member functions.
    142143    void setVisibleRect(const FloatRect&) override;
     144    void setLayoutViewportRect(Optional<FloatRect>) override;
    143145    void setCoverageRect(const FloatRect&) override;
    144146    bool tilesWouldChangeForCoverageRect(const FloatRect&) const override;
     
    191193
    192194    FloatRect m_visibleRect; // Only used for scroll performance logging.
     195    Optional<FloatRect> m_layoutViewportRect; // Only used by the tiled scrolling indicator.
    193196    FloatRect m_coverageRect;
    194197    IntRect m_boundsAtLastRevalidate;
  • trunk/Source/WebCore/platform/graphics/ca/TileCoverageMap.cpp

    r194607 r208213  
    3737    , m_updateTimer(*this, &TileCoverageMap::updateTimerFired)
    3838    , m_layer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeSimpleLayer, this))
    39     , m_visibleRectIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
     39    , m_visibleViewportIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
     40    , m_layoutViewportIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    4041    , m_coverageRectIndicatorLayer(*controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    4142    , m_position(FloatPoint(0, controller.topContentInset()))
     
    4849    m_layer.get().setContentsScale(m_controller.deviceScaleFactor());
    4950
    50     m_visibleRectIndicatorLayer.get().setName("visible rect indicator");
    51     m_visibleRectIndicatorLayer.get().setBorderWidth(2);
    52     m_visibleRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
    53     m_visibleRectIndicatorLayer.get().setBorderColor(Color(255, 0, 0));
     51    m_visibleViewportIndicatorLayer.get().setName("visible viewport indicator");
     52    m_visibleViewportIndicatorLayer.get().setBorderWidth(2);
     53    m_visibleViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
     54    m_visibleViewportIndicatorLayer.get().setBorderColor(Color(255, 0, 0, 200));
     55
     56    m_layoutViewportIndicatorLayer.get().setName("layout viewport indicator");
     57    m_layoutViewportIndicatorLayer.get().setBorderWidth(2);
     58    m_layoutViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
     59    m_layoutViewportIndicatorLayer.get().setBorderColor(Color(0, 128, 128, 200));
    5460   
    5561    m_coverageRectIndicatorLayer.get().setName("coverage indicator");
    56     m_coverageRectIndicatorLayer.get().setBorderWidth(2);
    5762    m_coverageRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
    58     m_coverageRectIndicatorLayer.get().setBorderColor(Color(0, 0, 128));
     63    m_coverageRectIndicatorLayer.get().setBackgroundColor(Color(64, 64, 64, 50));
    5964
    6065    m_layer.get().appendSublayer(m_coverageRectIndicatorLayer);
    61     m_layer.get().appendSublayer(m_visibleRectIndicatorLayer);
     66    m_layer.get().appendSublayer(m_visibleViewportIndicatorLayer);
     67   
     68    if (m_controller.layoutViewportRect())
     69        m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);
    6270
    6371    update();
     
    106114    visibleRect.scale(indicatorScale, indicatorScale);
    107115    visibleRect.expand(2, 2);
    108     m_visibleRectIndicatorLayer->setPosition(visibleRect.location());
    109     m_visibleRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size()));
     116    m_visibleViewportIndicatorLayer->setPosition(visibleRect.location());
     117    m_visibleViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size()));
     118
     119    if (auto layoutViewportRect = m_controller.layoutViewportRect()) {
     120        FloatRect layoutRect = layoutViewportRect.value();
     121        layoutRect.scale(indicatorScale, indicatorScale);
     122        layoutRect.expand(2, 2);
     123        m_layoutViewportIndicatorLayer->setPosition(layoutRect.location());
     124        m_layoutViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), layoutRect.size()));
     125
     126        if (!m_layoutViewportIndicatorLayer->superlayer())
     127            m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);
     128    } else if (m_layoutViewportIndicatorLayer->superlayer())
     129        m_layoutViewportIndicatorLayer->removeFromSuperlayer();
    110130
    111131    coverageRect.scale(indicatorScale, indicatorScale);
     
    130150    }
    131151
    132     m_visibleRectIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor);
     152    m_visibleViewportIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor);
    133153}
    134154
  • trunk/Source/WebCore/platform/graphics/ca/TileCoverageMap.h

    r197563 r208213  
    7272
    7373    Ref<PlatformCALayer> m_layer;
    74     Ref<PlatformCALayer> m_visibleRectIndicatorLayer;
     74    Ref<PlatformCALayer> m_visibleViewportIndicatorLayer;
     75    Ref<PlatformCALayer> m_layoutViewportIndicatorLayer;
    7576    Ref<PlatformCALayer> m_coverageRectIndicatorLayer;
    7677
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp

    r207631 r208213  
    461461    }
    462462   
    463     return view().frameView().viewportConstrainedVisibleContentRect();
     463    return view().frameView().rectForFixedPositionLayout();
    464464}
    465465
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r206662 r208213  
    520520        LayoutRect clippingBounds;
    521521        if (renderer().style().position() == FixedPosition && renderer().container() == &view)
    522             clippingBounds = view.frameView().viewportConstrainedVisibleContentRect();
     522            clippingBounds = view.frameView().rectForFixedPositionLayout();
    523523        else
    524524            clippingBounds = view.unscaledDocumentRect();
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r208068 r208213  
    27762776        viewBounds = m_renderView.unscaledDocumentRect();
    27772777    else
    2778         viewBounds = m_renderView.frameView().viewportConstrainedVisibleContentRect();
     2778        viewBounds = m_renderView.frameView().rectForFixedPositionLayout();
     2779
    27792780    LayoutRect layerBounds = layer.calculateLayerBounds(&layer, LayoutSize(), RenderLayer::UseLocalClipRectIfPossible | RenderLayer::IncludeLayerFilterOutsets | RenderLayer::UseFragmentBoxesExcludingCompositing
    27802781        | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants);
     
    37193720
    37203721    GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer();
    3721     LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect();
     3722    LayoutRect viewportRect = m_renderView.frameView().rectForFixedPositionLayout();
    37223723
    37233724    FixedPositionViewportConstraints constraints;
  • trunk/Source/WebCore/rendering/RenderTreeAsText.cpp

    r201052 r208213  
    3737#include "HTMLSpanElement.h"
    3838#include "InlineTextBox.h"
     39#include "Logging.h"
    3940#include "PrintContext.h"
    4041#include "PseudoElement.h"
     
    884885    if (!renderer->hasLayer())
    885886        return ts.release();
    886        
     887
     888    LOG(Layout, "externalRepresentation: dumping layer tree");
     889
    887890    RenderLayer* layer = renderer->layer();
    888891    writeLayers(ts, layer, layer, layer->rect(), 0, behavior);
  • trunk/Source/WebCore/testing/Internals.cpp

    r208207 r208213  
    10821082}
    10831083
     1084ExceptionOr<Ref<ClientRect>> Internals::layoutViewportRect()
     1085{
     1086    Document* document = contextDocument();
     1087    if (!document || !document->frame())
     1088        return Exception { INVALID_ACCESS_ERR };
     1089
     1090    document->updateLayoutIgnorePendingStylesheets();
     1091
     1092    auto& frameView = *document->view();
     1093    return ClientRect::create(frameView.layoutViewportRect());
     1094}
     1095
     1096ExceptionOr<Ref<ClientRect>> Internals::visualViewportRect()
     1097{
     1098    Document* document = contextDocument();
     1099    if (!document || !document->frame())
     1100        return Exception { INVALID_ACCESS_ERR };
     1101
     1102    document->updateLayoutIgnorePendingStylesheets();
     1103
     1104    auto& frameView = *document->view();
     1105    return ClientRect::create(frameView.visualViewportRect());
     1106}
     1107
    10841108ExceptionOr<void> Internals::setViewBaseBackgroundColor(const String& colorValue)
    10851109{
  • trunk/Source/WebCore/testing/Internals.h

    r208207 r208213  
    161161
    162162    ExceptionOr<void> setScrollViewPosition(int x, int y);
     163   
     164    ExceptionOr<Ref<ClientRect>> layoutViewportRect();
     165    ExceptionOr<Ref<ClientRect>> visualViewportRect();
     166   
    163167    ExceptionOr<void> setViewBaseBackgroundColor(const String& colorValue);
    164168
  • trunk/Source/WebCore/testing/Internals.idl

    r208207 r208213  
    148148    [MayThrowException] void setScrollViewPosition(long x, long y);
    149149
     150    [MayThrowException] ClientRect layoutViewportRect();
     151    [MayThrowException] ClientRect visualViewportRect();
     152
    150153    [MayThrowException] void setViewBaseBackgroundColor(DOMString colorValue);
    151154
  • trunk/Source/WebKit2/ChangeLog

    r208209 r208213  
     12016-10-31  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add basic visual/layout viewport support for fixed position layout
     4        https://bugs.webkit.org/show_bug.cgi?id=164261
     5
     6        Reviewed by Dean Jackson.
     7
     8        Don't make visualViewportEnabled an experimental feature, because I don't want it enabled
     9        by default in WebKitTestRunner (and therefore mismatching DumpRenderTree).
     10
     11        * Shared/WebPreferencesDefinitions.h:
     12
    1132016-10-29  Filip Pizlo  <fpizlo@apple.com>
    214
  • trunk/Source/WebKit2/Shared/WebPreferencesDefinitions.h

    r207562 r208213  
    232232    macro(ApplePayEnabled, applePayEnabled, Bool, bool, false, "", "") \
    233233    macro(ApplePayCapabilityDisclosureAllowed, applePayCapabilityDisclosureAllowed, Bool, bool, true, "", "") \
     234    macro(VisualViewportEnabled, visualViewportEnabled, Bool, bool, false, "", "") \
    234235    \
    235236
     
    295296    macro(VariationFontsEnabled, variationFontsEnabled, Bool, bool, true, "Variation Fonts", "Enable variation fonts") \
    296297    macro(InputEventsEnabled, inputEventsEnabled, Bool, bool, false, "Input Events", "Enable InputEvents support") \
    297     macro(VisualViewportEnabled, visualViewportEnabled, Bool, bool, false, "Visual Viewport", "Use Visual Viewport for fixed elements when zooming") \
    298298    macro(WebGL2Enabled, webGL2Enabled, Bool, bool, true, "WebGL 2.0", "WebGL 2 prototype") \
    299299    \
  • trunk/Tools/ChangeLog

    r208209 r208213  
     12016-10-31  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Add basic visual/layout viewport support for fixed position layout
     4        https://bugs.webkit.org/show_bug.cgi?id=164261
     5
     6        Reviewed by Dean Jackson.
     7
     8        Don't give tests in the "visual-viewport" directory a flexible viewport.
     9
     10        * DumpRenderTree/mac/DumpRenderTree.mm:
     11        (shouldMakeViewportFlexible):
     12        * WebKitTestRunner/TestOptions.cpp:
     13        (WTR::shouldMakeViewportFlexible):
     14
    1152016-10-29  Filip Pizlo  <fpizlo@apple.com>
    216
  • trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm

    r208089 r208213  
    18121812static bool shouldMakeViewportFlexible(const char* pathOrURL)
    18131813{
    1814     return strstr(pathOrURL, "viewport/");
     1814    return strstr(pathOrURL, "viewport/") && !strstr(pathOrURL, "visual-viewport/");
    18151815}
    18161816#endif
  • trunk/Tools/WebKitTestRunner/TestOptions.cpp

    r201904 r208213  
    4040static bool shouldMakeViewportFlexible(const std::string& pathOrURL)
    4141{
    42     return pathContains(pathOrURL, "viewport/");
     42    return pathContains(pathOrURL, "viewport/") && !pathContains(pathOrURL, "visual-viewport/");
    4343}
    4444
Note: See TracChangeset for help on using the changeset viewer.