Changeset 216803 in webkit


Ignore:
Timestamp:
May 12, 2017, 4:48:12 PM (8 years ago)
Author:
Simon Fraser
Message:

Incorrect position when dragging jQuery Draggable elements with position fixed after pinch zoom
https://bugs.webkit.org/show_bug.cgi?id=171113
Source/WebCore:

rdar://problem/31746516

Reviewed by Tim Horton.

Make getBoundingClientRect() and getClientRects() return rects which are relative to the layout
viewport, rather than the visual viewport. This goes part of the way to fixing webkit.org/b/170981,
which aims to make pinch-zoom invisible to web pages ("inert visual viewport"). It fixes issues on various
sites like Facebook when zoomed.

Factor coordinate conversion code into functions on FrameView, which now documents
the various coordinate systems in a big comment. Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale()
and Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale() are renamed and factored
to use these helpers.

There are two behavior changes here:

  1. FrameView::documentToClientOffset() now uses the origin of the layout viewport in the "document to client" coordinate mapping.
  1. The two document functions would apply the scale and offset in the wrong order. We need to first undo the effects of CSS zoom, page zoom and page scale, and then map from document to client coordinates.

Tests: fast/visual-viewport/client-rects-relative-to-layout-viewport.html

fast/zooming/client-rects-with-css-and-page-zoom.html

  • dom/Document.cpp:

(WebCore::Document::convertAbsoluteToClientQuads):
(WebCore::Document::convertAbsoluteToClientRect):
(WebCore::Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale): Deleted.
(WebCore::Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale): Deleted.

  • dom/Document.h:
  • dom/Element.cpp:

(WebCore::Element::getClientRects):
(WebCore::Element::getBoundingClientRect):

  • dom/Range.cpp:

(WebCore::Range::borderAndTextQuads):

  • page/FrameView.cpp:

(WebCore::FrameView::absoluteToDocumentScaleFactor):
(WebCore::FrameView::absoluteToDocumentRect):
(WebCore::FrameView::absoluteToDocumentPoint):
(WebCore::FrameView::documentToClientOffset):
(WebCore::FrameView::documentToClientRect):
(WebCore::FrameView::documentToClientPoint):

  • page/FrameView.h:
  • platform/ScrollableArea.h: #pragma once
  • platform/Scrollbar.h: #pragma once
  • platform/Widget.h: #pragma once

LayoutTests:

Reviewed by Tim Horton.

Rebaseline tests which dumped the getBoundingClientRect for fixed elements; now that these
are layout viewport-relative, getBoundingClientRect() for a fixed element is unchanging.

New test that exercises getBoundingClientRect() and getClientRects() for fixed and absolute
elements after zooming.

  • fast/events/autoscroll-when-zoomed.html: Adjust to account for behavior change.
  • fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt: Added.
  • fast/visual-viewport/client-rects-relative-to-layout-viewport.html: Added.
  • 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:
  • fast/zooming/client-rects-with-css-and-page-zoom-expected.txt: Added.
  • fast/zooming/client-rects-with-css-and-page-zoom.html: Added.
  • platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt: Added.
  • platform/ios/TestExpectations: Mark imported/w3c/web-platform-tests/cssom-view/elementFromPoint.html as failing;

it will be fixed via webkit.org/b/172019

  • platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt:
  • platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
Location:
trunk
Files:
5 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r216801 r216803  
     12017-05-11  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Incorrect position when dragging jQuery Draggable elements with position fixed after pinch zoom
     4        https://bugs.webkit.org/show_bug.cgi?id=171113
     5
     6        Reviewed by Tim Horton.
     7
     8        Rebaseline tests which dumped the getBoundingClientRect for fixed elements; now that these
     9        are layout viewport-relative, getBoundingClientRect() for a fixed element is unchanging.
     10
     11        New test that exercises getBoundingClientRect() and getClientRects() for fixed and absolute
     12        elements after zooming.
     13
     14        * fast/events/autoscroll-when-zoomed.html: Adjust to account for behavior change.
     15        * fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt: Added.
     16        * fast/visual-viewport/client-rects-relative-to-layout-viewport.html: Added.
     17        * fast/visual-viewport/zoomed-fixed-expected.txt:
     18        * fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
     19        * fast/zooming/client-rect-in-fixed-zoomed-expected.txt:
     20        * fast/zooming/client-rect-in-fixed-zoomed.html:
     21        * fast/zooming/client-rects-with-css-and-page-zoom-expected.txt: Added.
     22        * fast/zooming/client-rects-with-css-and-page-zoom.html: Added.
     23        * platform/ios-wk2/fast/visual-viewport/client-rects-relative-to-layout-viewport-expected.txt: Added.
     24        * platform/ios/TestExpectations: Mark imported/w3c/web-platform-tests/cssom-view/elementFromPoint.html as failing;
     25            it will be fixed via webkit.org/b/172019
     26        * platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt:
     27        * platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt:
     28
    1292017-05-12  Mark Lam  <mark.lam@apple.com>
    230
  • trunk/LayoutTests/fast/events/autoscroll-when-zoomed.html

    r210147 r216803  
    7373           
    7474            window.scrollTo(0, containerRect.bottom - lineHeight);
    75 
    7675            containerRect = document.getElementById('container').getBoundingClientRect(); // Scrolling changed it.
    7776
    78             start = { x: containerRect.left + 10, y: containerRect.bottom - lineHeight / 3 };
     77            start = { x: containerRect.left + 10, y: 2 * lineHeight / 3 };
    7978            end = { x: containerRect.right - 10, y: 16 };
    8079           
  • trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-expected.txt

    r215956 r216803  
    1919JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":392.5,"height":292.5,"top":525,"right":867.5,"bottom":817.5,"left":475}
    2020client rect of top:
    21 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}
     21JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
    2222client rect of bottom:
    23 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}
     23JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
    2424client rect of left:
    25 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}
     25JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
    2626client rect of right:
    27 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}
     27JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
    2828
    2929Scrolled to 100, 776
     
    3131JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":392.5,"height":292.5,"top":776,"right":492.5,"bottom":1068.5,"left":100}
    3232client rect of top:
    33 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}
     33JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
    3434client rect of bottom:
    35 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}
     35JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
    3636client rect of left:
    37 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}
     37JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
    3838client rect of right:
    39 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}
     39JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
    4040
    4141Scrolled to 50, 300
  • trunk/LayoutTests/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt

    r215956 r216803  
    1919JSON.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}
    2020client rect of top:
    21 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-314,"width":785,"height":100,"top":-314,"right":392.5,"bottom":-214,"left":-392.5}
     21JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
    2222client rect of bottom:
    23 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":171,"width":785,"height":100,"top":171,"right":392.5,"bottom":271,"left":-392.5}
     23JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
    2424client rect of left:
    25 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-392.5,"y":-314,"width":100,"height":585,"top":-314,"right":-292.5,"bottom":271,"left":-392.5}
     25JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
    2626client rect of right:
    27 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":292.5,"y":-314,"width":100,"height":585,"top":-314,"right":392.5,"bottom":271,"left":292.5}
     27JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
    2828
    2929Scrolled to 100, 776
     
    3131JSON.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}
    3232client rect of top:
    33 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-314,"width":785,"height":100,"top":-314,"right":767.5,"bottom":-214,"left":-17.5}
     33JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
    3434client rect of bottom:
    35 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":171,"width":785,"height":100,"top":171,"right":767.5,"bottom":271,"left":-17.5}
     35JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
    3636client rect of left:
    37 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-17.5,"y":-314,"width":100,"height":585,"top":-314,"right":82.5,"bottom":271,"left":-17.5}
     37JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
    3838client rect of right:
    39 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":667.5,"y":-314,"width":100,"height":585,"top":-314,"right":767.5,"bottom":271,"left":667.5}
     39JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
    4040
    4141Scrolled to 50, 300
     
    4343JSON.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}
    4444client rect of top:
    45 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":-21.5,"width":785,"height":100,"top":-21.5,"right":785,"bottom":78.5,"left":0}
     45JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":785,"height":100,"top":0,"right":785,"bottom":100,"left":0}
    4646client rect of bottom:
    47 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":463.5,"width":785,"height":100,"top":463.5,"right":785,"bottom":563.5,"left":0}
     47JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":485,"width":785,"height":100,"top":485,"right":785,"bottom":585,"left":0}
    4848client rect of left:
    49 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":-21.5,"width":100,"height":585,"top":-21.5,"right":100,"bottom":563.5,"left":0}
     49JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":585,"top":0,"right":100,"bottom":585,"left":0}
    5050client rect of right:
    51 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":-21.5,"width":100,"height":585,"top":-21.5,"right":785,"bottom":563.5,"left":685}
     51JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":685,"y":0,"width":100,"height":585,"top":0,"right":785,"bottom":585,"left":685}
    5252PASS successfullyParsed is true
    5353
  • trunk/LayoutTests/fast/zooming/client-rect-in-fixed-zoomed-expected.txt

    r215892 r216803  
    55
    66PASS internals.pageScaleFactor() is 2
    7 PASS JSON.stringify(clientRect) is JSON.stringify({x: 22, y: -108, width: 20, height: 10, top: -108, right: 42, bottom: -98, left: 22})
     7PASS JSON.stringify(clientRect) is JSON.stringify({x: 22, y: 32, width: 20, height: 10, top: 32, right: 42, bottom:42, left: 22})
    88PASS successfullyParsed is true
    99
  • trunk/LayoutTests/fast/zooming/client-rect-in-fixed-zoomed.html

    r215892 r216803  
    4141            clientRect = box.getBoundingClientRect();
    4242           
    43             shouldBe('JSON.stringify(clientRect)', 'JSON.stringify({x: 22, y: -108, width: 20, height: 10, top: -108, right: 42, bottom: -98, left: 22})');
     43            shouldBe('JSON.stringify(clientRect)', 'JSON.stringify({x: 22, y: 32, width: 20, height: 10, top: 32, right: 42, bottom:42, left: 22})');
    4444           
    4545            finishJSTest();
  • trunk/LayoutTests/platform/ios/TestExpectations

    r216696 r216803  
    29542954webkit.org/b/171760 imported/w3c/i18n/bidi/bidi-plaintext-011.html [ ImageOnlyFailure ]
    29552955webkit.org/b/171760 imported/w3c/i18n/bidi/block-plaintext-005.html [ ImageOnlyFailure ]
     2956
     2957webkit.org/b/172019 imported/w3c/web-platform-tests/cssom-view/elementFromPoint.html [ Failure ]
  • trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-expected.txt

    r216044 r216803  
    1919JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":525,"width":400,"height":300,"top":525,"right":875,"bottom":825,"left":475}
    2020client rect of top:
    21 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-525,"width":800,"height":100,"top":-525,"right":325,"bottom":-425,"left":-475}
     21JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    2222client rect of bottom:
    23 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-25,"width":800,"height":100,"top":-25,"right":325,"bottom":75,"left":-475}
     23JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    2424client rect of left:
    25 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-525,"width":100,"height":600,"top":-525,"right":-375,"bottom":75,"left":-475}
     25JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    2626client rect of right:
    27 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":225,"y":-525,"width":100,"height":600,"top":-525,"right":325,"bottom":75,"left":225}
     27JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    2828
    2929Scrolled to 100, 776
     
    3131JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":776,"width":400,"height":300,"top":776,"right":500,"bottom":1076,"left":100}
    3232client rect of top:
    33 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-776,"width":800,"height":100,"top":-776,"right":700,"bottom":-676,"left":-100}
     33JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    3434client rect of bottom:
    35 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-276,"width":800,"height":100,"top":-276,"right":700,"bottom":-176,"left":-100}
     35JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    3636client rect of left:
    37 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-776,"width":100,"height":600,"top":-776,"right":0,"bottom":-176,"left":-100}
     37JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    3838client rect of right:
    39 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":600,"y":-776,"width":100,"height":600,"top":-776,"right":700,"bottom":-176,"left":600}
     39JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    4040
    4141Scrolled to 50, 300
     
    4343JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":300,"width":400,"height":300,"top":300,"right":450,"bottom":600,"left":50}
    4444client rect of top:
    45 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":800,"height":100,"top":-300,"right":750,"bottom":-200,"left":-50}
     45JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    4646client rect of bottom:
    47 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":200,"width":800,"height":100,"top":200,"right":750,"bottom":300,"left":-50}
     47JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    4848client rect of left:
    49 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":100,"height":600,"top":-300,"right":50,"bottom":300,"left":-50}
     49JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    5050client rect of right:
    51 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":650,"y":-300,"width":100,"height":600,"top":-300,"right":750,"bottom":300,"left":650}
     51JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    5252PASS successfullyParsed is true
    5353
  • trunk/LayoutTests/platform/ios/fast/visual-viewport/zoomed-fixed-header-and-footer-expected.txt

    r216044 r216803  
    1919JSON.stringify(internals.visualViewportRect()) is {"x":475,"y":482,"width":400,"height":300,"top":482,"right":875,"bottom":782,"left":475}
    2020client rect of top:
    21 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-525,"width":800,"height":100,"top":-525,"right":325,"bottom":-425,"left":-475}
     21JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    2222client rect of bottom:
    23 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-25,"width":800,"height":100,"top":-25,"right":325,"bottom":75,"left":-475}
     23JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    2424client rect of left:
    25 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-475,"y":-525,"width":100,"height":600,"top":-525,"right":-375,"bottom":75,"left":-475}
     25JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    2626client rect of right:
    27 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":225,"y":-525,"width":100,"height":600,"top":-525,"right":325,"bottom":75,"left":225}
     27JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    2828
    2929Scrolled to 100, 776
     
    3131JSON.stringify(internals.visualViewportRect()) is {"x":100,"y":733,"width":400,"height":300,"top":733,"right":500,"bottom":1033,"left":100}
    3232client rect of top:
    33 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-776,"width":800,"height":100,"top":-776,"right":700,"bottom":-676,"left":-100}
     33JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    3434client rect of bottom:
    35 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-276,"width":800,"height":100,"top":-276,"right":700,"bottom":-176,"left":-100}
     35JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    3636client rect of left:
    37 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-100,"y":-776,"width":100,"height":600,"top":-776,"right":0,"bottom":-176,"left":-100}
     37JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    3838client rect of right:
    39 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":600,"y":-776,"width":100,"height":600,"top":-776,"right":700,"bottom":-176,"left":600}
     39JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    4040
    4141Scrolled to 50, 300
     
    4343JSON.stringify(internals.visualViewportRect()) is {"x":50,"y":257,"width":400,"height":300,"top":257,"right":450,"bottom":557,"left":50}
    4444client rect of top:
    45 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":800,"height":100,"top":-300,"right":750,"bottom":-200,"left":-50}
     45JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":800,"height":100,"top":0,"right":800,"bottom":100,"left":0}
    4646client rect of bottom:
    47 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":200,"width":800,"height":100,"top":200,"right":750,"bottom":300,"left":-50}
     47JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":500,"width":800,"height":100,"top":500,"right":800,"bottom":600,"left":0}
    4848client rect of left:
    49 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":-50,"y":-300,"width":100,"height":600,"top":-300,"right":50,"bottom":300,"left":-50}
     49JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":0,"y":0,"width":100,"height":600,"top":0,"right":100,"bottom":600,"left":0}
    5050client rect of right:
    51 JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":650,"y":-300,"width":100,"height":600,"top":-300,"right":750,"bottom":300,"left":650}
     51JSON.stringify(fixedElement.getBoundingClientRect()) is {"x":700,"y":0,"width":100,"height":600,"top":0,"right":800,"bottom":600,"left":700}
    5252PASS successfullyParsed is true
    5353
  • trunk/Source/WebCore/ChangeLog

    r216801 r216803  
     12017-05-11  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Incorrect position when dragging jQuery Draggable elements with position fixed after pinch zoom
     4        https://bugs.webkit.org/show_bug.cgi?id=171113
     5        rdar://problem/31746516
     6
     7        Reviewed by Tim Horton.
     8
     9        Make getBoundingClientRect() and getClientRects() return rects which are relative to the layout
     10        viewport, rather than the visual viewport. This goes part of the way to fixing webkit.org/b/170981,
     11        which aims to make pinch-zoom invisible to web pages ("inert visual viewport"). It fixes issues on various
     12        sites like Facebook when zoomed.
     13
     14        Factor coordinate conversion code into functions on FrameView, which now documents
     15        the various coordinate systems in a big comment. Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale()
     16        and Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale() are renamed and factored
     17        to use these helpers.
     18
     19        There are two behavior changes here:
     20
     21        1. FrameView::documentToClientOffset() now uses the origin of the layout viewport in the "document to client"
     22           coordinate mapping.
     23           
     24        2. The two document functions would apply the scale and offset in the wrong order. We need
     25           to first undo the effects of CSS zoom, page zoom and page scale, and then map from document
     26           to client coordinates.
     27
     28        Tests: fast/visual-viewport/client-rects-relative-to-layout-viewport.html
     29               fast/zooming/client-rects-with-css-and-page-zoom.html
     30
     31        * dom/Document.cpp:
     32        (WebCore::Document::convertAbsoluteToClientQuads):
     33        (WebCore::Document::convertAbsoluteToClientRect):
     34        (WebCore::Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale): Deleted.
     35        (WebCore::Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale): Deleted.
     36        * dom/Document.h:
     37        * dom/Element.cpp:
     38        (WebCore::Element::getClientRects):
     39        (WebCore::Element::getBoundingClientRect):
     40        * dom/Range.cpp:
     41        (WebCore::Range::borderAndTextQuads):
     42        * page/FrameView.cpp:
     43        (WebCore::FrameView::absoluteToDocumentScaleFactor):
     44        (WebCore::FrameView::absoluteToDocumentRect):
     45        (WebCore::FrameView::absoluteToDocumentPoint):
     46        (WebCore::FrameView::documentToClientOffset):
     47        (WebCore::FrameView::documentToClientRect):
     48        (WebCore::FrameView::documentToClientPoint):
     49        * page/FrameView.h:
     50        * platform/ScrollableArea.h: #pragma once
     51        * platform/Scrollbar.h: #pragma once
     52        * platform/Widget.h: #pragma once
     53
    1542017-05-12  Mark Lam  <mark.lam@apple.com>
    255
  • trunk/Source/WebCore/dom/Document.cpp

    r216778 r216803  
    64106410}
    64116411
    6412 void Document::adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(Vector<FloatQuad>& quads, const RenderStyle& style)
     6412void Document::convertAbsoluteToClientQuads(Vector<FloatQuad>& quads, const RenderStyle& style)
    64136413{
    64146414    if (!view())
    64156415        return;
    64166416
    6417     float zoom = style.effectiveZoom();
    6418     float inverseFrameScale = 1;
    6419     if (frame())
    6420         inverseFrameScale = 1 / frame()->frameScaleFactor();
    6421 
    6422     LayoutRect visibleContentRect = view()->visibleContentRect();
     6417    const auto& frameView = *view();
     6418    float inverseFrameScale = frameView.absoluteToDocumentScaleFactor(style.effectiveZoom());
     6419    auto documentToClientOffset = frameView.documentToClientOffset();
     6420
    64236421    for (auto& quad : quads) {
    6424         quad.move(-visibleContentRect.x(), -visibleContentRect.y());
    6425         if (zoom != 1)
    6426             quad.scale(1 / zoom);
    64276422        if (inverseFrameScale != 1)
    64286423            quad.scale(inverseFrameScale);
    6429     }
    6430 }
    6431 
    6432 void Document::adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(FloatRect& rect, const RenderStyle& style)
     6424
     6425        quad.move(documentToClientOffset);
     6426    }
     6427}
     6428
     6429void Document::convertAbsoluteToClientRect(FloatRect& rect, const RenderStyle& style)
    64336430{
    64346431    if (!view())
    64356432        return;
    64366433
    6437     float zoom = style.effectiveZoom();
    6438     float inverseFrameScale = 1;
    6439     if (frame())
    6440         inverseFrameScale = 1 / frame()->frameScaleFactor();
    6441 
    6442     LayoutRect visibleContentRect = view()->visibleContentRect();
    6443     rect.move(-visibleContentRect.x(), -visibleContentRect.y());
    6444     if (zoom != 1)
    6445         rect.scale(1 / zoom);
    6446     if (inverseFrameScale != 1)
    6447         rect.scale(inverseFrameScale);
     6434    const auto& frameView = *view();
     6435    rect = frameView.absoluteToDocumentRect(rect, style.effectiveZoom());
     6436    rect = frameView.documentToClientRect(rect);
    64486437}
    64496438
  • trunk/Source/WebCore/dom/Document.h

    r216632 r216803  
    12001200#endif
    12011201
    1202     void adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(Vector<FloatQuad>&, const RenderStyle&);
    1203     void adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(FloatRect&, const RenderStyle&);
     1202    void convertAbsoluteToClientQuads(Vector<FloatQuad>&, const RenderStyle&);
     1203    void convertAbsoluteToClientRect(FloatRect&, const RenderStyle&);
    12041204
    12051205    bool hasActiveParser();
  • trunk/Source/WebCore/dom/Element.cpp

    r216632 r216803  
    11581158    Vector<FloatQuad> quads;
    11591159    renderBoxModelObject->absoluteQuads(quads);
    1160     document().adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(quads, renderBoxModelObject->style());
     1160    document().convertAbsoluteToClientQuads(quads, renderBoxModelObject->style());
    11611161    return createDOMRectVector(quads);
    11621162}
     
    11861186        result.unite(quads[i].boundingBox());
    11871187
    1188     document().adjustFloatRectForScrollAndAbsoluteZoomAndFrameScale(result, renderer()->style());
     1188    document().convertAbsoluteToClientRect(result, renderer()->style());
    11891189    return DOMRect::create(result);
    11901190}
    11911191
     1192// Note that this is not web-exposed, and does not use the same coordinate system as getBoundingClientRect() and friends.
    11921193IntRect Element::clientRect() const
    11931194{
  • trunk/Source/WebCore/dom/Range.cpp

    r216259 r216803  
    17981798                renderer->absoluteQuads(elementQuads);
    17991799                if (space == CoordinateSpace::Client)
    1800                     node->document().adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(elementQuads, renderer->style());
     1800                    node->document().convertAbsoluteToClientQuads(elementQuads, renderer->style());
    18011801                quads.appendVector(elementQuads);
    18021802            }
     
    18071807                auto textQuads = renderer->absoluteQuadsForRange(startOffset, endOffset);
    18081808                if (space == CoordinateSpace::Client)
    1809                     node->document().adjustFloatQuadsForScrollAndAbsoluteZoomAndFrameScale(textQuads, renderer->style());
     1809                    node->document().convertAbsoluteToClientQuads(textQuads, renderer->style());
    18101810                quads.appendVector(textQuads);
    18111811            }
  • trunk/Source/WebCore/page/FrameView.cpp

    r216778 r216803  
    49074907}
    49084908
     4909float FrameView::absoluteToDocumentScaleFactor(std::optional<float> effectiveZoom) const
     4910{
     4911    // If effectiveZoom is passed, it already factors in pageZoomFactor().
     4912    float cssZoom = effectiveZoom.value_or(frame().pageZoomFactor());
     4913    return 1 / (cssZoom * frame().frameScaleFactor());
     4914}
     4915
     4916FloatRect FrameView::absoluteToDocumentRect(FloatRect rect, std::optional<float> effectiveZoom) const
     4917{
     4918    rect.scale(absoluteToDocumentScaleFactor(effectiveZoom));
     4919    return rect;
     4920}
     4921
     4922FloatPoint FrameView::absoluteToDocumentPoint(FloatPoint p, std::optional<float> effectiveZoom) const
     4923{
     4924    p.scale(absoluteToDocumentScaleFactor(effectiveZoom));
     4925    return p;
     4926}
     4927
     4928FloatSize FrameView::documentToClientOffset() const
     4929{
     4930    return frame().settings().visualViewportEnabled() ? -toFloatSize(layoutViewportRect().location()) : -toFloatSize(visibleContentRect().location());
     4931}
     4932
     4933FloatRect FrameView::documentToClientRect(FloatRect rect) const
     4934{
     4935    rect.move(documentToClientOffset());
     4936    return rect;
     4937}
     4938
     4939FloatPoint FrameView::documentToClientPoint(FloatPoint p) const
     4940{
     4941    p.move(documentToClientOffset());
     4942    return p;
     4943}
     4944
    49094945void FrameView::setTracksRepaints(bool trackRepaints)
    49104946{
  • trunk/Source/WebCore/page/FrameView.h

    r216541 r216803  
    430430    WEBCORE_EXPORT void scrollElementToRect(const Element&, const IntRect&);
    431431
     432    // Coordinate systems:
     433    //
     434    // "View"
     435    //     Top left is top left of the FrameView/ScrollView/Widget. Size is Widget::boundsRect().size().
     436    //
     437    // "TotalContents"
     438    //    Relative to ScrollView's scrolled contents, including headers and footers. Size is totalContentsSize().
     439    //
     440    // "Contents"
     441    //    Relative to ScrollView's scrolled contents, excluding headers and footers, so top left is top left of the scroll view's
     442    //    document, and size is contentsSize().
     443    //
     444    // "Absolute"
     445    //    Relative to the document's scroll origin (non-zero for RTL documents), but affected by page zoom and page scale. Mostly used
     446    //    in rendering code.
     447    //
     448    // "Document"
     449    //    Relative to the document's scroll origin, but not affected by page zoom or page scale. Size is equivalent to CSS pixel dimensions.
     450    //
     451    // "Client"
     452    //    Relative to the visible part of the document (or, more strictly, the layout viewport rect), and with the same scaling
     453    //    as Document coordinates, i.e. matching CSS pixels. Affected by scroll origin.
     454    //   
     455
    432456    // Methods to convert points and rects between the coordinate space of the renderer, and this view.
    433457    WEBCORE_EXPORT IntRect convertFromRendererToContainingView(const RenderElement*, const IntRect&) const;
     
    441465    IntPoint convertToContainingView(const IntPoint&) const final;
    442466    IntPoint convertFromContainingView(const IntPoint&) const final;
     467
     468    float absoluteToDocumentScaleFactor(std::optional<float> effectiveZoom = std::nullopt) const;
     469    FloatRect absoluteToDocumentRect(FloatRect, std::optional<float> effectiveZoom = std::nullopt) const;
     470    FloatPoint absoluteToDocumentPoint(FloatPoint, std::optional<float> effectiveZoom = std::nullopt) const;
     471
     472    FloatSize documentToClientOffset() const;
     473    FloatRect documentToClientRect(FloatRect) const;
     474    FloatPoint documentToClientPoint(FloatPoint) const;
    443475
    444476    bool isFrameViewScrollCorner(const RenderScrollbarPart& scrollCorner) const { return m_scrollCorner == &scrollCorner; }
  • trunk/Source/WebCore/platform/ScrollableArea.h

    r210560 r216803  
    2424 */
    2525
    26 #ifndef ScrollableArea_h
    27 #define ScrollableArea_h
     26#pragma once
    2827
    2928#include "ScrollSnapOffsetsInfo.h"
     
    392391} // namespace WebCore
    393392
    394 #endif // ScrollableArea_h
  • trunk/Source/WebCore/platform/Scrollbar.h

    r216541 r216803  
    2424 */
    2525
    26 #ifndef Scrollbar_h
    27 #define Scrollbar_h
     26#pragma once
    2827
    2928#include "ScrollTypes.h"
     
    193192SPECIALIZE_TYPE_TRAITS_WIDGET(Scrollbar, isScrollbar())
    194193
    195 #endif // Scrollbar_h
  • trunk/Source/WebCore/platform/Widget.h

    r216541 r216803  
    2525 */
    2626
    27 #ifndef Widget_h
    28 #define Widget_h
     27#pragma once
    2928
    3029#if PLATFORM(IOS)
     
    262261SPECIALIZE_TYPE_TRAITS_END()
    263262
    264 #endif // Widget_h
Note: See TracChangeset for help on using the changeset viewer.