Changeset 219342 in webkit


Ignore:
Timestamp:
Jul 11, 2017 11:01:15 AM (7 years ago)
Author:
commit-queue@webkit.org
Message:

elementFromPoint() should consider x and y to be in client (layout viewport) coordinates
https://bugs.webkit.org/show_bug.cgi?id=172019

Patch by Ali Juma <ajuma@chromium.org> on 2017-07-11
Reviewed by Simon Fraser.

Source/WebCore:

When visual viewports are enabled, this makes TreeScope::nodeFromPoint consider its
input to be in client coordinates, and clips this input to the layout viewport. This change
affects the behavior of document.elementFromPoint() and document.caretRangeFromPoint.

No new tests. Modified an existing test, and made a previously-failing test pass on ios.

  • dom/TreeScope.cpp:

(WebCore::TreeScope::nodeFromPoint):

  • page/FrameView.cpp:

(WebCore::FrameView::layoutViewportToAbsoluteRect):
(WebCore::FrameView::layoutViewportToAbsolutePoint):
(WebCore::FrameView::clientToLayoutViewportPoint):

  • page/FrameView.h:
  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::hitTest):

LayoutTests:

  • fast/dom/elementFromPoint-scaled-scrolled-expected.txt: Updated.
  • fast/dom/elementFromPoint-scaled-scrolled.html: Updated.
  • platform/ios/TestExpectations:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r219339 r219342  
     12017-07-11  Ali Juma  <ajuma@chromium.org>
     2
     3        elementFromPoint() should consider x and y to be in client (layout viewport) coordinates
     4        https://bugs.webkit.org/show_bug.cgi?id=172019
     5
     6        Reviewed by Simon Fraser.
     7
     8        * fast/dom/elementFromPoint-scaled-scrolled-expected.txt: Updated.
     9        * fast/dom/elementFromPoint-scaled-scrolled.html: Updated.
     10        * platform/ios/TestExpectations:
     11
    1122017-07-11  Charlie Turner  <cturner@igalia.com>
    213
  • trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled-expected.txt

    r134135 r219342  
    1 B1B2B3
    2 This test is successful if elementFromPoint returns the correct element.
    3 B3
     1This test applies page scale and scrolls the page, and checks that elementFromPoint returns the correct element.
     2
     3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
     4
     5
     6PASS successfullyParsed is true
     7
     8TEST COMPLETE
     9PASS document.elementFromPoint(225, 125) is b1
     10PASS document.elementFromPoint(525, 425) is b2
     11PASS document.elementFromPoint(225, 125) is b1
     12PASS document.elementFromPoint(525, 425) is b2
     13PASS document.elementFromPoint(115, 15) is b1
     14PASS document.elementFromPoint(415, 315) is b2
     15PASS document.elementFromPoint(-85, 15) is null
     16PASS document.elementFromPoint(215, 315) is b2
     17PASS successfullyParsed is true
     18
     19TEST COMPLETE
     20
  • trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled.html

    r155265 r219342  
    22<html>
    33<head>
    4 <script src="../../../../resources/js-test-pre.js"></script>
     4<style>
     5    body {
     6        width: 2000px;
     7        height: 2000px;
     8    }
     9    button {
     10        position: absolute;
     11        width: 50px;
     12        height: 50px;
     13    }
     14    #b1 {
     15        left: 200px;
     16        top: 100px;
     17    }
     18    #b2 {
     19        left: 500px;
     20        top: 400px;
     21    }
     22</style>
     23<script src="../../resources/js-test-pre.js"></script>
    524</head>
    625<body onload="runTest();" style="width:2000px;height:2000px;margin:0px;padding:100px">
    7 <button style="width:50px;height:50px;">B1</button><button style="width:50px;height:50px;">B2</button><button style="width:50px;height:50px;">B3</button>
    8 <div>This test is successful if elementFromPoint returns the correct element.</div>
    9 <div id="result"></div>
     26<button id="b1"></button>
     27<button id="b2"></button>
    1028<script>
    1129function runTest() {
    12     if (window.internals)
     30    description("This test applies page scale and scrolls the page, and checks that elementFromPoint returns the correct element.");
     31    if (window.internals) {
     32        window.internals.settings.setVisualViewportEnabled(true);
    1333        window.internals.setPageScaleFactor(2, 0, 0);
    14     window.scrollTo(100,100);
     34    }
     35    window.scrollTo(100, 100);
    1536
    16     if (window.testRunner)
    17         testRunner.dumpAsText();
     37    // The layout viewport hasn't been scrolled.
     38    shouldBe("document.elementFromPoint(225, 125)", "b1");
     39    shouldBe("document.elementFromPoint(525, 425)", "b2");
    1840
    19     document.getElementById("result").innerText = document.elementFromPoint(125, 25).innerText;
     41    window.scrollTo(200, 200);
     42
     43    // b1 is now offscreen, but still within the layout viewport.
     44    shouldBe("document.elementFromPoint(225, 125)", "b1");
     45    shouldBe("document.elementFromPoint(525, 425)", "b2");
     46
     47    window.scrollTo(500, 400);
     48    shouldBe("document.elementFromPoint(115, 15)", "b1");
     49    shouldBe("document.elementFromPoint(415, 315)", "b2");
     50
     51    window.scrollTo(700, 400);
     52    shouldBeNull("document.elementFromPoint(-85, 15)");
     53    shouldBe("document.elementFromPoint(215, 315)", "b2");
     54
     55    finishJSTest();
    2056}
    2157</script>
    22 </script>
     58<script src="../../resources/js-test-post.js"></script>
    2359</body>
    2460</html>
  • trunk/LayoutTests/platform/ios/TestExpectations

    r219299 r219342  
    27202720
    27212721# Test relies on window.scrollTo
     2722fast/dom/elementFromPoint-scaled-scrolled.html [ Skip ]
    27222723fast/zooming/client-rect-in-fixed-zoomed.html [ Skip ]
    27232724fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed.html [ Skip ]
     
    28172818webkit.org/b/171760 imported/w3c/i18n/bidi/bidi-plaintext-011.html [ ImageOnlyFailure ]
    28182819webkit.org/b/171760 imported/w3c/i18n/bidi/block-plaintext-005.html [ ImageOnlyFailure ]
    2819 
    2820 webkit.org/b/172019 imported/w3c/web-platform-tests/cssom-view/elementFromPoint.html [ Failure ]
    28212820
    28222821webkit.org/b/172547 http/tests/xmlhttprequest/xmlhttprequest-50ms-download-dispatch.html [ Failure ]
  • trunk/Source/WebCore/ChangeLog

    r219341 r219342  
     12017-07-11  Ali Juma  <ajuma@chromium.org>
     2
     3        elementFromPoint() should consider x and y to be in client (layout viewport) coordinates
     4        https://bugs.webkit.org/show_bug.cgi?id=172019
     5
     6        Reviewed by Simon Fraser.
     7
     8        When visual viewports are enabled, this makes TreeScope::nodeFromPoint consider its
     9        input to be in client coordinates, and clips this input to the layout viewport. This change
     10        affects the behavior of document.elementFromPoint() and document.caretRangeFromPoint.
     11
     12        No new tests. Modified an existing test, and made a previously-failing test pass on ios.
     13
     14        * dom/TreeScope.cpp:
     15        (WebCore::TreeScope::nodeFromPoint):
     16        * page/FrameView.cpp:
     17        (WebCore::FrameView::layoutViewportToAbsoluteRect):
     18        (WebCore::FrameView::layoutViewportToAbsolutePoint):
     19        (WebCore::FrameView::clientToLayoutViewportPoint):
     20        * page/FrameView.h:
     21        * rendering/RenderLayer.cpp:
     22        (WebCore::RenderLayer::hitTest):
     23
    1242017-07-11  Timothy Hatcher  <timothy@hatcher.name>
    225
  • trunk/Source/WebCore/dom/TreeScope.cpp

    r217972 r219342  
    4545#include "RenderView.h"
    4646#include "RuntimeEnabledFeatures.h"
     47#include "Settings.h"
    4748#include "ShadowRoot.h"
    4849#include <wtf/text/CString.h>
     
    302303        return nullptr;
    303304
    304     float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
    305 
    306     LayoutPoint contentsPoint = clientPoint;
    307     contentsPoint.scale(scaleFactor);
    308     contentsPoint.moveBy(view->contentsScrollPosition());
    309 
    310     LayoutRect visibleRect;
     305    LayoutPoint absolutePoint;
     306    if (frame->settings().visualViewportEnabled()) {
     307        documentScope().updateLayout();
     308        FloatPoint layoutViewportPoint = view->clientToLayoutViewportPoint(clientPoint);
     309        FloatRect layoutViewportBounds({ }, view->layoutViewportRect().size());
     310        if (!layoutViewportBounds.contains(layoutViewportPoint))
     311            return nullptr;
     312        absolutePoint = LayoutPoint(view->layoutViewportToAbsolutePoint(layoutViewportPoint));
     313    } else {
     314        float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
     315
     316        absolutePoint = clientPoint;
     317        absolutePoint.scale(scaleFactor);
     318        absolutePoint.moveBy(view->contentsScrollPosition());
     319
     320        LayoutRect visibleRect;
    311321#if PLATFORM(IOS)
    312     visibleRect = view->unobscuredContentRect();
     322        visibleRect = view->unobscuredContentRect();
    313323#else
    314     visibleRect = view->visibleContentRect();
     324        visibleRect = view->visibleContentRect();
    315325#endif
    316     if (!visibleRect.contains(contentsPoint))
    317         return nullptr;
    318 
    319     HitTestResult result(contentsPoint);
     326        if (!visibleRect.contains(absolutePoint))
     327            return nullptr;
     328    }
     329
     330    HitTestResult result(absolutePoint);
    320331    documentScope().renderView()->hitTest(HitTestRequest(), result);
    321332
  • trunk/Source/WebCore/page/FrameView.cpp

    r219320 r219342  
    49374937}
    49384938
     4939FloatRect FrameView::layoutViewportToAbsoluteRect(FloatRect rect) const
     4940{
     4941    ASSERT(frame().settings().visualViewportEnabled());
     4942    rect.moveBy(layoutViewportRect().location());
     4943    rect.scale(frame().frameScaleFactor());
     4944    return rect;
     4945}
     4946
     4947FloatPoint FrameView::layoutViewportToAbsolutePoint(FloatPoint p) const
     4948{
     4949    ASSERT(frame().settings().visualViewportEnabled());
     4950    p.moveBy(layoutViewportRect().location());
     4951    return p.scaled(frame().frameScaleFactor());
     4952}
     4953
     4954FloatPoint FrameView::clientToLayoutViewportPoint(FloatPoint p) const
     4955{
     4956    ASSERT(frame().settings().visualViewportEnabled());
     4957    return p.scaled(frame().pageZoomFactor());
     4958}
     4959
    49394960void FrameView::setTracksRepaints(bool trackRepaints)
    49404961{
  • trunk/Source/WebCore/page/FrameView.h

    r219320 r219342  
    455455    //    Relative to the visible part of the document (or, more strictly, the layout viewport rect), and with the same scaling
    456456    //    as Document coordinates, i.e. matching CSS pixels. Affected by scroll origin.
    457     //   
     457    //
     458    // "LayoutViewport"
     459    //    Similar to client coordinates, but affected by page zoom (but not page scale).
     460    //
    458461
    459462    // Methods to convert points and rects between the coordinate space of the renderer, and this view.
     
    478481    FloatRect documentToClientRect(FloatRect) const;
    479482    FloatPoint documentToClientPoint(FloatPoint) const;
     483
     484    FloatRect layoutViewportToAbsoluteRect(FloatRect) const;
     485    FloatPoint layoutViewportToAbsolutePoint(FloatPoint) const;
     486
     487    // Unlike client coordinates, layout viewport coordinates are affected by page zoom.
     488    FloatPoint clientToLayoutViewportPoint(FloatPoint) const;
    480489
    481490    bool isFrameViewScrollCorner(const RenderScrollbarPart& scrollCorner) const { return m_scrollCorner == &scrollCorner; }
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r218928 r219342  
    49254925    updateLayerListsIfNeeded();
    49264926
    4927     LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? downcast<RenderFlowThread>(renderer()).visualOverflowRect() : renderer().view().documentRect();
    4928     if (!request.ignoreClipping())
    4929         hitTestArea.intersect(renderer().view().frameView().visibleContentRect(LegacyIOSDocumentVisibleRect));
     4927    ASSERT(!isRenderFlowThread());
     4928    LayoutRect hitTestArea = renderer().view().documentRect();
     4929    if (!request.ignoreClipping()) {
     4930        if (renderer().settings().visualViewportEnabled()) {
     4931            auto& frameView = renderer().view().frameView();
     4932            LayoutRect layoutViewportBounds({ }, frameView.layoutViewportRect().size());
     4933            LayoutRect absoluteLayoutViewportRect = LayoutRect(frameView.layoutViewportToAbsoluteRect(layoutViewportBounds));
     4934            hitTestArea.intersect(absoluteLayoutViewportRect);
     4935        } else
     4936            hitTestArea.intersect(renderer().view().frameView().visibleContentRect(LegacyIOSDocumentVisibleRect));
     4937    }
    49304938
    49314939    RenderLayer* insideLayer = hitTestLayer(this, nullptr, request, result, hitTestArea, hitTestLocation, false);
Note: See TracChangeset for help on using the changeset viewer.