Changeset 237284 in webkit


Ignore:
Timestamp:
Oct 19, 2018 6:47:25 AM (6 years ago)
Author:
ajuma@chromium.org
Message:

[IntersectionObserver] Handle zero-area intersections
https://bugs.webkit.org/show_bug.cgi?id=189624

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

Rebaseline expectations for tests that now pass.

  • web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt:
  • web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt:
  • web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt:
  • web-platform-tests/intersection-observer/text-target-expected.txt:
  • web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt:

Source/WebCore:

Use edge-inclusive intersection when applying clips and intersecting with the
root, so that two rects that touch each other are considered intersecting even
if the area of their intersection is 0.

Covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.

  • dom/Document.cpp:

(WebCore::computeIntersectionState):
(WebCore::Document::updateIntersectionObservations):
(WebCore::computeIntersectionRects): Deleted.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r237254 r237284  
     12018-10-19  Ali Juma  <ajuma@chromium.org>
     2
     3        [IntersectionObserver] Handle zero-area intersections
     4        https://bugs.webkit.org/show_bug.cgi?id=189624
     5
     6        Reviewed by Simon Fraser.
     7
     8        Rebaseline expectations for tests that now pass.
     9
     10        * web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt:
     11        * web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt:
     12        * web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt:
     13        * web-platform-tests/intersection-observer/text-target-expected.txt:
     14        * web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt:
     15
    1162018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
    217
  • trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt

    r235358 r237284  
    22PASS IntersectionObserver should detect and report edge-adjacent and zero-area intersections.
    33PASS First rAF.
    4 FAIL Set transform=translateY(200px) on target. assert_equals: entries.length expected 2 but got 1
    5 FAIL Set transform=translateY(201px) on target. assert_equals: entries.length expected 3 but got 1
    6 FAIL Set transform=translateY(185px) on target. assert_equals: entries.length expected 4 but got 1
     4PASS Set transform=translateY(200px) on target.
     5PASS Set transform=translateY(201px) on target.
     6PASS Set transform=translateY(185px) on target.
    77
  • trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt

    r235358 r237284  
    11
    22PASS isIntersecting changes should trigger notifications.
    3 FAIL Rects in initial notifications should report initial positions. assert_equals: entries[2].target.isIntersecting equals true expected true but got false
     3PASS Rects in initial notifications should report initial positions.
     4PASS Set scrollTop=100 and check for no new notifications.
     5PASS Add 4th target.
     6PASS Set scrollTop=100 and check for one new notification.
    47
  • trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt

    r235459 r237284  
    22PASS Observing a zero-area target.
    33PASS First rAF
    4 FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
    5 FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
     4PASS document.scrollingElement.scrollTop = 300
     5PASS document.scrollingElement.scrollTop = 100
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt

    r235459 r237284  
    33PASS IntersectionObserver observing a br element.
    44PASS First rAF.
    5 FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
    6 FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
     5PASS document.scrollingElement.scrollTop = 300
     6PASS document.scrollingElement.scrollTop = 100
    77
  • trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt

    r235014 r237284  
    11
    22PASS Ensure that a zero-area target intersecting root generates a notification with intersectionRatio == 1
    3 FAIL First rAF should generate a notification. assert_equals: intersectionRatio == 1 expected 1 but got 0
     3PASS First rAF should generate a notification.
    44
  • trunk/Source/WebCore/ChangeLog

    r237281 r237284  
     12018-10-19  Ali Juma  <ajuma@chromium.org>
     2
     3        [IntersectionObserver] Handle zero-area intersections
     4        https://bugs.webkit.org/show_bug.cgi?id=189624
     5
     6        Reviewed by Simon Fraser.
     7
     8        Use edge-inclusive intersection when applying clips and intersecting with the
     9        root, so that two rects that touch each other are considered intersecting even
     10        if the area of their intersection is 0.
     11
     12        Covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.
     13
     14        * dom/Document.cpp:
     15        (WebCore::computeIntersectionState):
     16        (WebCore::Document::updateIntersectionObservations):
     17        (WebCore::computeIntersectionRects): Deleted.
     18
    1192018-10-18  Eric Carlson  <eric.carlson@apple.com>
    220
  • trunk/Source/WebCore/dom/Document.cpp

    r237266 r237284  
    75937593}
    75947594
    7595 static void computeIntersectionRects(FrameView& frameView, IntersectionObserver& observer, Element& target, FloatRect& absTargetRect, FloatRect& absIntersectionRect, FloatRect& absRootBounds)
     7595struct IntersectionObservationState {
     7596    FloatRect absoluteTargetRect;
     7597    FloatRect absoluteRootBounds;
     7598    FloatRect absoluteIntersectionRect;
     7599    bool isIntersecting { false };
     7600};
     7601
     7602static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target)
    75967603{
    75977604    // FIXME: Implement intersection computation for the cross-document case.
    75987605    if (observer.trackingDocument() != &target.document())
    7599         return;
     7606        return std::nullopt;
    76007607
    76017608    auto* targetRenderer = target.renderer();
    76027609    if (!targetRenderer)
    7603         return;
     7610        return std::nullopt;
    76047611
    76057612    FloatRect localRootBounds;
     
    76077614    if (observer.root()) {
    76087615        if (!observer.root()->renderer() || !is<RenderBlock>(observer.root()->renderer()))
    7609             return;
     7616            return std::nullopt;
    76107617
    76117618        rootRenderer = downcast<RenderBlock>(observer.root()->renderer());
    76127619        if (!rootRenderer->isContainingBlockAncestorFor(*targetRenderer))
    7613             return;
     7620            return std::nullopt;
    76147621
    76157622        if (rootRenderer->hasOverflowClip())
     
    76337640        localTargetBounds = downcast<RenderLineBreak>(targetRenderer)->linesBoundingBox();
    76347641
    7635     FloatRect rootLocalIntersectionRect = targetRenderer->computeRectForRepaint(localTargetBounds, rootRenderer);
    7636     rootLocalIntersectionRect.intersect(localRootBounds);
    7637 
    7638     if (!rootLocalIntersectionRect.isEmpty())
    7639         absIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
    7640 
    7641     absTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
    7642     absRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
     7642    OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
     7643    std::optional<LayoutRect> rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
     7644    FloatRect rootLocalIntersectionRect = localRootBounds;
     7645
     7646    IntersectionObservationState intersectionState;
     7647    intersectionState.isIntersecting = rootLocalTargetRect && rootLocalIntersectionRect.edgeInclusiveIntersect(*rootLocalTargetRect);
     7648
     7649    if (intersectionState.isIntersecting)
     7650        intersectionState.absoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
     7651
     7652    intersectionState.absoluteTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
     7653    intersectionState.absoluteRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
     7654    return intersectionState;
    76437655}
    76447656
     
    76687680            auto& registration = targetRegistrations[index];
    76697681
    7670             FloatRect absTargetRect;
    7671             FloatRect absIntersectionRect;
    7672             FloatRect absRootBounds;
    7673             computeIntersectionRects(*frameView, *observer, *target, absTargetRect, absIntersectionRect, absRootBounds);
    7674 
    7675             // FIXME: Handle zero-area intersections (e.g., intersections involving zero-area targets).
    7676             bool isIntersecting = absIntersectionRect.area();
    7677             float intersectionRatio = isIntersecting ? absIntersectionRect.area() / absTargetRect.area() : 0;
     7682            auto intersectionState = computeIntersectionState(*frameView, *observer, *target);
     7683
     7684            float intersectionRatio = 0;
    76787685            size_t thresholdIndex = 0;
    7679             if (isIntersecting) {
    7680                 auto& thresholds = observer->thresholds();
    7681                 while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
    7682                     ++thresholdIndex;
     7686            if (intersectionState) {
     7687                if (intersectionState->isIntersecting) {
     7688                    float absTargetArea = intersectionState->absoluteTargetRect.area();
     7689                    if (absTargetArea)
     7690                        intersectionRatio = intersectionState->absoluteIntersectionRect.area() / absTargetArea;
     7691                    else
     7692                        intersectionRatio = 1;
     7693
     7694                    auto& thresholds = observer->thresholds();
     7695                    while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
     7696                        ++thresholdIndex;
     7697                }
    76837698            }
    76847699
     7700
    76857701            if (!registration.previousThresholdIndex || thresholdIndex != registration.previousThresholdIndex) {
    7686                 FloatRect targetBoundingClientRect = frameView->absoluteToClientRect(absTargetRect);
    7687                 FloatRect clientIntersectionRect = isIntersecting ? frameView->absoluteToClientRect(absIntersectionRect) : FloatRect();
     7702                FloatRect targetBoundingClientRect;
     7703                FloatRect clientIntersectionRect;
     7704                FloatRect clientRootBounds;
     7705                if (intersectionState) {
     7706                    targetBoundingClientRect = frameView->absoluteToClientRect(intersectionState->absoluteTargetRect);
     7707                    clientRootBounds = frameView->absoluteToClientRect(intersectionState->absoluteRootBounds);
     7708                    if (intersectionState->isIntersecting)
     7709                        clientIntersectionRect = frameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);
     7710                }
    76887711
    76897712                // FIXME: Once cross-document observation is implemented, only report root bounds if the target document and
    76907713                // the root document are similar-origin.
    7691                 FloatRect clientRootBounds = frameView->absoluteToClientRect(absRootBounds);
    76927714                std::optional<DOMRectInit> reportedRootBounds = DOMRectInit({
    76937715                    clientRootBounds.x(),
     
    77047726                    intersectionRatio,
    77057727                    target,
    7706                     isIntersecting,
     7728                    intersectionState? intersectionState->isIntersecting : false,
    77077729                }));
    77087730                needNotify = true;
Note: See TracChangeset for help on using the changeset viewer.