Title: [219342] trunk
Revision
219342
Author
[email protected]
Date
2017-07-11 11:01:15 -0700 (Tue, 11 Jul 2017)

Log 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 <[email protected]> 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:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (219341 => 219342)


--- trunk/LayoutTests/ChangeLog	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/LayoutTests/ChangeLog	2017-07-11 18:01:15 UTC (rev 219342)
@@ -1,3 +1,14 @@
+2017-07-11  Ali Juma  <[email protected]>
+
+        elementFromPoint() should consider x and y to be in client (layout viewport) coordinates
+        https://bugs.webkit.org/show_bug.cgi?id=172019
+
+        Reviewed by Simon Fraser.
+
+        * fast/dom/elementFromPoint-scaled-scrolled-expected.txt: Updated.
+        * fast/dom/elementFromPoint-scaled-scrolled.html: Updated.
+        * platform/ios/TestExpectations:
+
 2017-07-11  Charlie Turner  <[email protected]>
 
         [GTK] compositing/video/poster.html passing since r218320

Modified: trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled-expected.txt (219341 => 219342)


--- trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled-expected.txt	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled-expected.txt	2017-07-11 18:01:15 UTC (rev 219342)
@@ -1,3 +1,20 @@
-B1B2B3
-This test is successful if elementFromPoint returns the correct element.
-B3
+This test applies page scale and scrolls the page, and checks that elementFromPoint returns the correct element.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS document.elementFromPoint(225, 125) is b1
+PASS document.elementFromPoint(525, 425) is b2
+PASS document.elementFromPoint(225, 125) is b1
+PASS document.elementFromPoint(525, 425) is b2
+PASS document.elementFromPoint(115, 15) is b1
+PASS document.elementFromPoint(415, 315) is b2
+PASS document.elementFromPoint(-85, 15) is null
+PASS document.elementFromPoint(215, 315) is b2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Modified: trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled.html (219341 => 219342)


--- trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled.html	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/LayoutTests/fast/dom/elementFromPoint-scaled-scrolled.html	2017-07-11 18:01:15 UTC (rev 219342)
@@ -1,24 +1,60 @@
 <!DOCTYPE html>
 <html>
 <head>
-<script src=""
+<style>
+    body {
+        width: 2000px;
+        height: 2000px;
+    }
+    button {
+        position: absolute;
+        width: 50px;
+        height: 50px;
+    }
+    #b1 {
+        left: 200px;
+        top: 100px;
+    }
+    #b2 {
+        left: 500px;
+        top: 400px;
+    }
+</style>
+<script src=""
 </head>
 <body _onload_="runTest();" style="width:2000px;height:2000px;margin:0px;padding:100px">
-<button style="width:50px;height:50px;">B1</button><button style="width:50px;height:50px;">B2</button><button style="width:50px;height:50px;">B3</button>
-<div>This test is successful if elementFromPoint returns the correct element.</div>
-<div id="result"></div>
+<button id="b1"></button>
+<button id="b2"></button>
 <script>
 function runTest() {
-    if (window.internals)
+    description("This test applies page scale and scrolls the page, and checks that elementFromPoint returns the correct element.");
+    if (window.internals) {
+        window.internals.settings.setVisualViewportEnabled(true);
         window.internals.setPageScaleFactor(2, 0, 0);
-    window.scrollTo(100,100);
+    }
+    window.scrollTo(100, 100);
 
-    if (window.testRunner)
-        testRunner.dumpAsText();
+    // The layout viewport hasn't been scrolled.
+    shouldBe("document.elementFromPoint(225, 125)", "b1");
+    shouldBe("document.elementFromPoint(525, 425)", "b2");
 
-    document.getElementById("result").innerText = document.elementFromPoint(125, 25).innerText;
+    window.scrollTo(200, 200);
+
+    // b1 is now offscreen, but still within the layout viewport.
+    shouldBe("document.elementFromPoint(225, 125)", "b1");
+    shouldBe("document.elementFromPoint(525, 425)", "b2");
+
+    window.scrollTo(500, 400);
+    shouldBe("document.elementFromPoint(115, 15)", "b1");
+    shouldBe("document.elementFromPoint(415, 315)", "b2");
+
+    window.scrollTo(700, 400);
+    shouldBeNull("document.elementFromPoint(-85, 15)");
+    shouldBe("document.elementFromPoint(215, 315)", "b2");
+
+    finishJSTest();
 }
 </script>
-</script>
+<script src=""
 </body>
 </html>

Modified: trunk/LayoutTests/platform/ios/TestExpectations (219341 => 219342)


--- trunk/LayoutTests/platform/ios/TestExpectations	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2017-07-11 18:01:15 UTC (rev 219342)
@@ -2719,6 +2719,7 @@
 webkit.org/b/163046 js/regress-141098.html [ Pass Failure ]
 
 # Test relies on window.scrollTo
+fast/dom/elementFromPoint-scaled-scrolled.html [ Skip ]
 fast/zooming/client-rect-in-fixed-zoomed.html [ Skip ]
 fast/visual-viewport/zoomed-scroll-to-anchor-in-position-fixed.html [ Skip ]
 fast/visual-viewport/zoomed-scroll-into-view-fixed.html [ Skip ]
@@ -2817,8 +2818,6 @@
 webkit.org/b/171760 imported/w3c/i18n/bidi/bidi-plaintext-011.html [ ImageOnlyFailure ]
 webkit.org/b/171760 imported/w3c/i18n/bidi/block-plaintext-005.html [ ImageOnlyFailure ]
 
-webkit.org/b/172019 imported/w3c/web-platform-tests/cssom-view/elementFromPoint.html [ Failure ]
-
 webkit.org/b/172547 http/tests/xmlhttprequest/xmlhttprequest-50ms-download-dispatch.html [ Failure ]
 
 webkit.org/b/172610 media/ios/autoplay-only-in-main-document.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (219341 => 219342)


--- trunk/Source/WebCore/ChangeLog	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/Source/WebCore/ChangeLog	2017-07-11 18:01:15 UTC (rev 219342)
@@ -1,3 +1,26 @@
+2017-07-11  Ali Juma  <[email protected]>
+
+        elementFromPoint() should consider x and y to be in client (layout viewport) coordinates
+        https://bugs.webkit.org/show_bug.cgi?id=172019
+
+        Reviewed by Simon Fraser.
+
+        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):
+
 2017-07-11  Timothy Hatcher  <[email protected]>
 
         Broken build when !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)

Modified: trunk/Source/WebCore/dom/TreeScope.cpp (219341 => 219342)


--- trunk/Source/WebCore/dom/TreeScope.cpp	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/Source/WebCore/dom/TreeScope.cpp	2017-07-11 18:01:15 UTC (rev 219342)
@@ -44,6 +44,7 @@
 #include "PointerLockController.h"
 #include "RenderView.h"
 #include "RuntimeEnabledFeatures.h"
+#include "Settings.h"
 #include "ShadowRoot.h"
 #include <wtf/text/CString.h>
 
@@ -301,22 +302,32 @@
     if (!frame || !view)
         return nullptr;
 
-    float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
+    LayoutPoint absolutePoint;
+    if (frame->settings().visualViewportEnabled()) {
+        documentScope().updateLayout();
+        FloatPoint layoutViewportPoint = view->clientToLayoutViewportPoint(clientPoint);
+        FloatRect layoutViewportBounds({ }, view->layoutViewportRect().size());
+        if (!layoutViewportBounds.contains(layoutViewportPoint))
+            return nullptr;
+        absolutePoint = LayoutPoint(view->layoutViewportToAbsolutePoint(layoutViewportPoint));
+    } else {
+        float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
 
-    LayoutPoint contentsPoint = clientPoint;
-    contentsPoint.scale(scaleFactor);
-    contentsPoint.moveBy(view->contentsScrollPosition());
+        absolutePoint = clientPoint;
+        absolutePoint.scale(scaleFactor);
+        absolutePoint.moveBy(view->contentsScrollPosition());
 
-    LayoutRect visibleRect;
+        LayoutRect visibleRect;
 #if PLATFORM(IOS)
-    visibleRect = view->unobscuredContentRect();
+        visibleRect = view->unobscuredContentRect();
 #else
-    visibleRect = view->visibleContentRect();
+        visibleRect = view->visibleContentRect();
 #endif
-    if (!visibleRect.contains(contentsPoint))
-        return nullptr;
+        if (!visibleRect.contains(absolutePoint))
+            return nullptr;
+    }
 
-    HitTestResult result(contentsPoint);
+    HitTestResult result(absolutePoint);
     documentScope().renderView()->hitTest(HitTestRequest(), result);
 
     if (localPoint)

Modified: trunk/Source/WebCore/page/FrameView.cpp (219341 => 219342)


--- trunk/Source/WebCore/page/FrameView.cpp	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/Source/WebCore/page/FrameView.cpp	2017-07-11 18:01:15 UTC (rev 219342)
@@ -4936,6 +4936,27 @@
     return p;
 }
 
+FloatRect FrameView::layoutViewportToAbsoluteRect(FloatRect rect) const
+{
+    ASSERT(frame().settings().visualViewportEnabled());
+    rect.moveBy(layoutViewportRect().location());
+    rect.scale(frame().frameScaleFactor());
+    return rect;
+}
+
+FloatPoint FrameView::layoutViewportToAbsolutePoint(FloatPoint p) const
+{
+    ASSERT(frame().settings().visualViewportEnabled());
+    p.moveBy(layoutViewportRect().location());
+    return p.scaled(frame().frameScaleFactor());
+}
+
+FloatPoint FrameView::clientToLayoutViewportPoint(FloatPoint p) const
+{
+    ASSERT(frame().settings().visualViewportEnabled());
+    return p.scaled(frame().pageZoomFactor());
+}
+
 void FrameView::setTracksRepaints(bool trackRepaints)
 {
     if (trackRepaints == m_isTrackingRepaints)

Modified: trunk/Source/WebCore/page/FrameView.h (219341 => 219342)


--- trunk/Source/WebCore/page/FrameView.h	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/Source/WebCore/page/FrameView.h	2017-07-11 18:01:15 UTC (rev 219342)
@@ -454,7 +454,10 @@
     // "Client"
     //    Relative to the visible part of the document (or, more strictly, the layout viewport rect), and with the same scaling
     //    as Document coordinates, i.e. matching CSS pixels. Affected by scroll origin.
-    //    
+    //
+    // "LayoutViewport"
+    //    Similar to client coordinates, but affected by page zoom (but not page scale).
+    //
 
     // Methods to convert points and rects between the coordinate space of the renderer, and this view.
     WEBCORE_EXPORT IntRect convertFromRendererToContainingView(const RenderElement*, const IntRect&) const;
@@ -478,6 +481,12 @@
     FloatRect documentToClientRect(FloatRect) const;
     FloatPoint documentToClientPoint(FloatPoint) const;
 
+    FloatRect layoutViewportToAbsoluteRect(FloatRect) const;
+    FloatPoint layoutViewportToAbsolutePoint(FloatPoint) const;
+
+    // Unlike client coordinates, layout viewport coordinates are affected by page zoom.
+    FloatPoint clientToLayoutViewportPoint(FloatPoint) const;
+
     bool isFrameViewScrollCorner(const RenderScrollbarPart& scrollCorner) const { return m_scrollCorner == &scrollCorner; }
 
     // isScrollable() takes an optional Scrollability parameter that allows the caller to define what they mean by 'scrollable.'

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (219341 => 219342)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2017-07-11 17:58:22 UTC (rev 219341)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2017-07-11 18:01:15 UTC (rev 219342)
@@ -4924,9 +4924,17 @@
     
     updateLayerListsIfNeeded();
 
-    LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? downcast<RenderFlowThread>(renderer()).visualOverflowRect() : renderer().view().documentRect();
-    if (!request.ignoreClipping())
-        hitTestArea.intersect(renderer().view().frameView().visibleContentRect(LegacyIOSDocumentVisibleRect));
+    ASSERT(!isRenderFlowThread());
+    LayoutRect hitTestArea = renderer().view().documentRect();
+    if (!request.ignoreClipping()) {
+        if (renderer().settings().visualViewportEnabled()) {
+            auto& frameView = renderer().view().frameView();
+            LayoutRect layoutViewportBounds({ }, frameView.layoutViewportRect().size());
+            LayoutRect absoluteLayoutViewportRect = LayoutRect(frameView.layoutViewportToAbsoluteRect(layoutViewportBounds));
+            hitTestArea.intersect(absoluteLayoutViewportRect);
+        } else
+            hitTestArea.intersect(renderer().view().frameView().visibleContentRect(LegacyIOSDocumentVisibleRect));
+    }
 
     RenderLayer* insideLayer = hitTestLayer(this, nullptr, request, result, hitTestArea, hitTestLocation, false);
     if (!insideLayer) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to