On macOS, getBoundingClientRect gives incorrect values when pinch-zoomed
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Jan 2018 19:53:08 +0000 (19:53 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Jan 2018 19:53:08 +0000 (19:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181511
rdar://problem/33741427

Reviewed by Zalan Bujtas.
Source/WebCore:

When reverting "client coordinates are relative to layout viewport" in r219829
I broke documentToClientOffset() on macOS by failing to take pinch zoom scale into
account (frameScaleFactor() is always 1 on iOs, so this bug doesn't manifest there).

Covered by existing tests.

* page/FrameView.cpp:
(WebCore::FrameView::documentToClientOffset const):

LayoutTests:

New results in tests that get client coordinates after zooming.

* fast/visual-viewport/client-coordinates-relative-to-layout-viewport-expected.txt:
* fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt:
* fast/visual-viewport/client-rects-relative-to-layout-viewport-zoomed.html:
* fast/visual-viewport/zoomed-fixed-expected.txt:
* fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
* fast/zooming/client-rect-in-fixed-zoomed-expected.txt:
* fast/zooming/client-rect-in-fixed-zoomed.html: Change the test to create passing results.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226791 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/visual-viewport/client-coordinates-relative-to-layout-viewport-expected.txt
LayoutTests/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt
LayoutTests/fast/visual-viewport/client-rects-relative-to-layout-viewport-zoomed.html
LayoutTests/fast/visual-viewport/zoomed-fixed-expected.txt
LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt
LayoutTests/fast/zooming/client-rect-in-fixed-zoomed-expected.txt
LayoutTests/fast/zooming/client-rect-in-fixed-zoomed.html
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp

index 5f5a28b..46ca2c0 100644 (file)
@@ -1,3 +1,21 @@
+2018-01-10  Simon Fraser  <simon.fraser@apple.com>
+
+        On macOS, getBoundingClientRect gives incorrect values when pinch-zoomed
+        https://bugs.webkit.org/show_bug.cgi?id=181511
+        rdar://problem/33741427
+
+        Reviewed by Zalan Bujtas.
+
+        New results in tests that get client coordinates after zooming.
+
+        * fast/visual-viewport/client-coordinates-relative-to-layout-viewport-expected.txt:
+        * fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt:
+        * fast/visual-viewport/client-rects-relative-to-layout-viewport-zoomed.html:
+        * fast/visual-viewport/zoomed-fixed-expected.txt:
+        * fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
+        * fast/zooming/client-rect-in-fixed-zoomed-expected.txt:
+        * fast/zooming/client-rect-in-fixed-zoomed.html: Change the test to create passing results.
+
 2018-01-11  Eric Carlson  <eric.carlson@apple.com>
 
         Layout Test media/event-queue-crash.html is flaky
index 0173cac..37362fa 100644 (file)
@@ -6,16 +6,16 @@ layer at (0,0) size 785x3024
       RenderBlock {P} at (0,0) size 2000x18
         RenderText {#text} at (0,0) size 79x18
           text run at (0,0) width 79: "Got click at "
-        RenderInline {SPAN} at (0,0) size 104x18
-          RenderText {#text} at (78,0) size 104x18
-            text run at (78,0) width 104: "clicked at 52, -6"
-layer at (38,-20) size 28x28 backgroundClip at (0,0) size 2008x3024 clip at (0,0) size 2008x3024
-  RenderBlock (positioned) {DIV} at (38,-20) size 28x28 [bgcolor=#FF0000]
+        RenderInline {SPAN} at (0,0) size 122x18
+          RenderText {#text} at (78,0) size 122x18
+            text run at (78,0) width 122: "clicked at 172, 117"
+layer at (158,103) size 28x28
+  RenderBlock (positioned) {DIV} at (158,103) size 28x28 [bgcolor=#FF0000]
 layer at (280,228) size 25x25
   RenderBlock (positioned) {DIV} at (279,227) size 26x26 [bgcolor=#008000]
 layer at (281,229) size 22x22
   RenderBlock (positioned) {DIV} at (281,229) size 22x22 [bgcolor=#FFA500]
-layer at (44,-14) size 16x16 backgroundClip at (0,0) size 2008x3024 clip at (0,0) size 2008x3024
-  RenderBlock (positioned) {DIV} at (44,-14) size 16x16 [bgcolor=#0000FF]
+layer at (164,109) size 16x16
+  RenderBlock (positioned) {DIV} at (164,109) size 16x16 [bgcolor=#0000FF]
 caret: position 12 of child 0 {#text} of child 9 {P} of body
 scrolled to 120,123
index 034978f..20690eb 100644 (file)
@@ -13,26 +13,26 @@ absolute client rect: 120, 100 - 50 x 25
 Scrolled to 476, 526
 layoutViewport: 83.5, 233.5 - 785 x 585
 visualViewportRect: 476, 526 - 392.5 x 292.5
-fixed client bounds: -856.5, -808.5 - 30 x 20
-fixed client rect: -856.5, -808.5 - 30 x 20
-absolute client bounds: -832, -952 - 50 x 25
-absolute client rect: -832, -952 - 50 x 25
+fixed client bounds: -380.5, -282.5 - 30 x 20
+fixed client rect: -380.5, -282.5 - 30 x 20
+absolute client bounds: -356, -426 - 50 x 25
+absolute client rect: -356, -426 - 50 x 25
 
 Scrolled to 100, 776
 layoutViewport: 83.5, 483.5 - 785 x 585
 visualViewportRect: 100, 776 - 392.5 x 292.5
-fixed client bounds: -104.5, -1058.5 - 30 x 20
-fixed client rect: -104.5, -1058.5 - 30 x 20
-absolute client bounds: -80, -1452 - 50 x 25
-absolute client rect: -80, -1452 - 50 x 25
+fixed client bounds: -4.5, -282.5 - 30 x 20
+fixed client rect: -4.5, -282.5 - 30 x 20
+absolute client bounds: 20, -676 - 50 x 25
+absolute client rect: 20, -676 - 50 x 25
 
 Scrolled to 50, 300
 layoutViewport: 50, 300 - 785 x 585
 visualViewportRect: 50, 300 - 392.5 x 292.5
-fixed client bounds: -38, -290 - 30 x 20
-fixed client rect: -38, -290 - 30 x 20
-absolute client bounds: 20, -500 - 50 x 25
-absolute client rect: 20, -500 - 50 x 25
+fixed client bounds: 12, 10 - 30 x 20
+fixed client rect: 12, 10 - 30 x 20
+absolute client bounds: 70, -200 - 50 x 25
+absolute client rect: 70, -200 - 50 x 25
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 7e52e9b..f9217bf 100644 (file)
             var fixed = document.getElementById('fixed');
             var absolute = document.getElementById('absolute');
 
-            debug('layoutViewport: ' + stringFromRect(internals.layoutViewportRect()));
-            debug('visualViewportRect: ' + stringFromRect(internals.visualViewportRect()));
+            if (window.internals) {
+                debug('layoutViewport: ' + stringFromRect(internals.layoutViewportRect()));
+                debug('visualViewportRect: ' + stringFromRect(internals.visualViewportRect()));
+            }
 
             debug('fixed client bounds: ' + stringFromRect(fixed.getBoundingClientRect()));
             debug('fixed client rect: ' + stringFromRect(fixed.getClientRects()[0]));
@@ -55,9 +57,6 @@
 
         function doTest()
         {
-            if (!window.testRunner)
-                return;
-
             if (window.eventSender)
                 eventSender.zoomPageIn();
 
index 6f4afb5..38cf0f7 100644 (file)
@@ -18,37 +18,37 @@ Scrolled to 475, 525
 JSON.stringify(internals.layoutViewportRect()) is {"x":82.5,"y":232.5,"width":785,"height":585,"top":232.5,"right":867.5,"bottom":817.5,"left":82.5}
 JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":392.5,"height":292.5,"top":525,"right":867.5,"bottom":817.5,"left":475}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-817.5,"width":785,"height":100,"top":-817.5,"right":-82.5,"bottom":-717.5,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-292.5,"width":785,"height":100,"top":-292.5,"right":392.5,"bottom":-192.5,"left":-392.5}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-332.5,"width":785,"height":100,"top":-332.5,"right":-82.5,"bottom":-232.5,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":192.5,"width":785,"height":100,"top":192.5,"right":392.5,"bottom":292.5,"left":-392.5}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-817.5,"width":100,"height":585,"top":-817.5,"right":-767.5,"bottom":-232.5,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-292.5,"width":100,"height":585,"top":-292.5,"right":-292.5,"bottom":292.5,"left":-392.5}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-182.5,"y":-817.5,"width":100,"height":585,"top":-817.5,"right":-82.5,"bottom":-232.5,"left":-182.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":292.5,"y":-292.5,"width":100,"height":585,"top":-292.5,"right":392.5,"bottom":292.5,"left":292.5}
 
 Scrolled to 100, 776
 JSON.stringify(internals.layoutViewportRect()) is {"x":82.5,"y":483.5,"width":785,"height":585,"top":483.5,"right":867.5,"bottom":1068.5,"left":82.5}
 JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":392.5,"height":292.5,"top":776,"right":492.5,"bottom":1068.5,"left":100}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-1068.5,"width":785,"height":100,"top":-1068.5,"right":667.5,"bottom":-968.5,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-292.5,"width":785,"height":100,"top":-292.5,"right":767.5,"bottom":-192.5,"left":-17.5}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-583.5,"width":785,"height":100,"top":-583.5,"right":667.5,"bottom":-483.5,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":192.5,"width":785,"height":100,"top":192.5,"right":767.5,"bottom":292.5,"left":-17.5}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-1068.5,"width":100,"height":585,"top":-1068.5,"right":-17.5,"bottom":-483.5,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-292.5,"width":100,"height":585,"top":-292.5,"right":82.5,"bottom":292.5,"left":-17.5}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":567.5,"y":-1068.5,"width":100,"height":585,"top":-1068.5,"right":667.5,"bottom":-483.5,"left":567.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":667.5,"y":-292.5,"width":100,"height":585,"top":-292.5,"right":767.5,"bottom":292.5,"left":667.5}
 
 Scrolled to 50, 300
 JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":300,"width":785,"height":585,"top":300,"right":835,"bottom":885,"left":50}
 JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":392.5,"height":292.5,"top":300,"right":442.5,"bottom":592.5,"left":50}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":785,"height":100,"top":-300,"right":735,"bottom":-200,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":185,"width":785,"height":100,"top":185,"right":735,"bottom":285,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":100,"height":585,"top":-300,"right":50,"bottom":285,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":635,"y":-300,"width":100,"height":585,"top":-300,"right":735,"bottom":285,"left":635}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
 PASS successfullyParsed is true
 
 TEST COMPLETE
index b054e69..0c85851 100644 (file)
@@ -18,37 +18,37 @@ Scrolled to 475, 525
 JSON.stringify(internals.layoutViewportRect()) is {"x":82.5,"y":211,"width":785,"height":585,"top":211,"right":867.5,"bottom":796,"left":82.5}
 JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":503.5,"width":392.5,"height":292.5,"top":503.5,"right":867.5,"bottom":796,"left":475}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-839,"width":785,"height":100,"top":-839,"right":-82.5,"bottom":-739,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-314,"width":785,"height":100,"top":-314,"right":392.5,"bottom":-214,"left":-392.5}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-354,"width":785,"height":100,"top":-354,"right":-82.5,"bottom":-254,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":171,"width":785,"height":100,"top":171,"right":392.5,"bottom":271,"left":-392.5}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-867.5,"y":-839,"width":100,"height":585,"top":-839,"right":-767.5,"bottom":-254,"left":-867.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-314,"width":100,"height":585,"top":-314,"right":-292.5,"bottom":271,"left":-392.5}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-182.5,"y":-839,"width":100,"height":585,"top":-839,"right":-82.5,"bottom":-254,"left":-182.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":292.5,"y":-314,"width":100,"height":585,"top":-314,"right":392.5,"bottom":271,"left":292.5}
 
 Scrolled to 100, 776
 JSON.stringify(internals.layoutViewportRect()) is {"x":82.5,"y":462,"width":785,"height":585,"top":462,"right":867.5,"bottom":1047,"left":82.5}
 JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":754.5,"width":392.5,"height":292.5,"top":754.5,"right":492.5,"bottom":1047,"left":100}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-1090,"width":785,"height":100,"top":-1090,"right":667.5,"bottom":-990,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-314,"width":785,"height":100,"top":-314,"right":767.5,"bottom":-214,"left":-17.5}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-605,"width":785,"height":100,"top":-605,"right":667.5,"bottom":-505,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":171,"width":785,"height":100,"top":171,"right":767.5,"bottom":271,"left":-17.5}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-117.5,"y":-1090,"width":100,"height":585,"top":-1090,"right":-17.5,"bottom":-505,"left":-117.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-314,"width":100,"height":585,"top":-314,"right":82.5,"bottom":271,"left":-17.5}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":567.5,"y":-1090,"width":100,"height":585,"top":-1090,"right":667.5,"bottom":-505,"left":567.5}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":667.5,"y":-314,"width":100,"height":585,"top":-314,"right":767.5,"bottom":271,"left":667.5}
 
 Scrolled to 50, 300
 JSON.stringify(internals.layoutViewportRect()) is {"x":50,"y":278.5,"width":785,"height":585,"top":278.5,"right":835,"bottom":863.5,"left":50}
 JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":278.5,"width":392.5,"height":292.5,"top":278.5,"right":442.5,"bottom":571,"left":50}
 client rect of top:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-321.5,"width":785,"height":100,"top":-321.5,"right":735,"bottom":-221.5,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":-21.5,"width":785,"height":100,"top":-21.5,"right":785,"bottom":78.5,"left":0}
 client rect of bottom:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":163.5,"width":785,"height":100,"top":163.5,"right":735,"bottom":263.5,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":463.5,"width":785,"height":100,"top":463.5,"right":785,"bottom":563.5,"left":0}
 client rect of left:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-321.5,"width":100,"height":585,"top":-321.5,"right":50,"bottom":263.5,"left":-50}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":-21.5,"width":100,"height":585,"top":-21.5,"right":100,"bottom":563.5,"left":0}
 client rect of right:
-JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":635,"y":-321.5,"width":100,"height":585,"top":-321.5,"right":735,"bottom":263.5,"left":635}
+JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":-21.5,"width":100,"height":585,"top":-21.5,"right":785,"bottom":563.5,"left":685}
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 9f2f49f..666d26e 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS internals.pageScaleFactor() is 2
-FAIL JSON.stringify(clientRect) should be {"x":22,"y":32,"width":20,"height":10,"top":32,"right":42,"bottom":42,"left":22}. Was {"x":22,"y":-248,"width":20,"height":10,"top":-248,"right":42,"bottom":-238,"left":22}.
+PASS JSON.stringify(clientRect) is JSON.stringify({x: 22, y: -108, width: 20, height: 10, top: -108, right: 42, bottom:-98, left: 22})
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 31cf770..d074f6e 100644 (file)
@@ -40,7 +40,7 @@
             var box = document.getElementById('box');
             clientRect = box.getBoundingClientRect();
             
-            shouldBe('JSON.stringify(clientRect)', 'JSON.stringify({x: 22, y: 32, width: 20, height: 10, top: 32, right: 42, bottom:42, left: 22})');
+            shouldBe('JSON.stringify(clientRect)', 'JSON.stringify({x: 22, y: -108, width: 20, height: 10, top: -108, right: 42, bottom:-98, left: 22})');
             
             finishJSTest();
         }
index 13028e5..5891f88 100644 (file)
@@ -1,3 +1,20 @@
+2018-01-10  Simon Fraser  <simon.fraser@apple.com>
+
+        On macOS, getBoundingClientRect gives incorrect values when pinch-zoomed
+        https://bugs.webkit.org/show_bug.cgi?id=181511
+        rdar://problem/33741427
+
+        Reviewed by Zalan Bujtas.
+        
+        When reverting "client coordinates are relative to layout viewport" in r219829
+        I broke documentToClientOffset() on macOS by failing to take pinch zoom scale into
+        account (frameScaleFactor() is always 1 on iOs, so this bug doesn't manifest there).
+
+        Covered by existing tests.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::documentToClientOffset const):
+
 2018-01-11  Youenn Fablet  <youenn@apple.com>
 
         Replace WebRTCLegacyAPIDisabled by WebRTCLegacyAPIEnabled and switch off WebRTC legacy flag by default
index cb8dd1a..8154ae1 100644 (file)
@@ -4511,7 +4511,7 @@ FloatSize FrameView::documentToClientOffset() const
     FloatSize clientOrigin = -toFloatSize(visibleContentRect().location());
 
     // Layout and visual viewports are affected by page zoom, so we need to factor that out.
-    return clientOrigin.scaled(1 / frame().pageZoomFactor());
+    return clientOrigin.scaled(1 / (frame().pageZoomFactor() * frame().frameScaleFactor()));
 }
 
 FloatRect FrameView::documentToClientRect(FloatRect rect) const