Fix position:-webkit-sticky behavior when zoomed
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Dec 2012 18:07:56 +0000 (18:07 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Dec 2012 18:07:56 +0000 (18:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=105251

Reviewed by Dean Jackson.

Source/WebCore:

Position sticky elements were misplaced when stickily-constrained, under zooming.
The cause was that some of the functions used to compute sticky position
took page scale into account, and some did not.

Fix by using localToContainerQuad(..., view()) to compute RenderView-relative
quads, which avoids page scale, so all the constraints math is done ignoring
page scale. This also requires that we compute a scale-free viewport rect
in stickyPositionOffset().

Test: fast/css/sticky/sticky-top-zoomed.html

* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::computeStickyPositionConstraints):
(WebCore::RenderBoxModelObject::stickyPositionOffset):

LayoutTests:

Ref test for sticky elements in a zoomed page.

This test is marked as failing for WK1, because scrollbars always show on
zoomed pages and cannot be hidden there.

* fast/css/sticky/sticky-top-zoomed-expected.html: Added.
* fast/css/sticky/sticky-top-zoomed.html: Added.
* platform/mac-wk2/TestExpectations:
* platform/mac/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/fast/css/sticky/sticky-top-zoomed-expected.html [new file with mode: 0644]
LayoutTests/fast/css/sticky/sticky-top-zoomed.html [new file with mode: 0644]
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBoxModelObject.cpp

index dba0dc1..8682134 100644 (file)
@@ -1,3 +1,20 @@
+2012-12-17  Simon Fraser  <simon.fraser@apple.com>
+
+        Fix position:-webkit-sticky behavior when zoomed
+        https://bugs.webkit.org/show_bug.cgi?id=105251
+
+        Reviewed by Dean Jackson.
+
+        Ref test for sticky elements in a zoomed page.
+        
+        This test is marked as failing for WK1, because scrollbars always show on
+        zoomed pages and cannot be hidden there.
+
+        * fast/css/sticky/sticky-top-zoomed-expected.html: Added.
+        * fast/css/sticky/sticky-top-zoomed.html: Added.
+        * platform/mac-wk2/TestExpectations:
+        * platform/mac/TestExpectations:
+
 2012-12-18  Thiago Marcos P. Santos  <thiago.santos@intel.com>
 
         [EFL] Unreviewed gardening.
diff --git a/LayoutTests/fast/css/sticky/sticky-top-zoomed-expected.html b/LayoutTests/fast/css/sticky/sticky-top-zoomed-expected.html
new file mode 100644 (file)
index 0000000..ae761ac
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+    }
+
+    ::-webkit-scrollbar {
+        width: 0px;
+        height: 0px;
+    }
+    
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 160px;
+        height: 300px;
+    }
+    
+    .container {
+        width: 150px;
+        height: 300px;
+        outline: 2px solid black;
+    }
+    
+    .box {
+        width: 150px;
+        height: 150px;
+    }
+
+    .sticky {
+        position: -webkit-sticky;
+        top: 75px;
+        background-color: green;
+    }
+    
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+<script>
+    function doTest()
+    {
+        if (window.eventSender)
+            eventSender.scalePageBy(1.5);
+    }
+    window.addEventListener('load', doTest, false);
+</script>
+</head>
+<body>
+    <div class="group" style="top: -100px">
+        <div class="indicator box" style="top: 150px;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 0">
+        <div class="indicator box" style="top: 75px;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 0;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/sticky/sticky-top-zoomed.html b/LayoutTests/fast/css/sticky/sticky-top-zoomed.html
new file mode 100644 (file)
index 0000000..5f30dd4
--- /dev/null
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<style>
+    body {
+        margin: 0;
+        height: 2000px;
+    }
+
+    ::-webkit-scrollbar {
+        width: 0px;
+        height: 0px;
+    }
+    
+    .group {
+        display: inline-block;
+        position: relative;
+        width: 160px;
+        height: 300px;
+    }
+    
+    .container {
+        width: 150px;
+        height: 300px;
+        outline: 2px solid black;
+    }
+    
+    .box {
+        width: 150px;
+        height: 150px;
+    }
+
+    .sticky {
+        position: -webkit-sticky;
+        top: 75px;
+        background-color: green;
+    }
+    
+    .indicator {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background-color: red;
+    }
+</style>
+<script>
+    function doTest()
+    {
+        if (window.eventSender)
+            eventSender.scalePageBy(1.5);
+
+        window.scrollTo(0, 100);
+    }
+    window.addEventListener('load', doTest, false);
+</script>
+</head>
+<body>
+    <div class="group">
+        <div class="indicator box" style="top: 150px;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 100px">
+        <div class="indicator box" style="top: 75px;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+
+    <div class="group" style="top: 200px">
+        <div class="indicator box" style="top: 0;"></div>
+        <div class="container">
+            <div class="sticky box"></div>
+        </div>
+    </div>
+</body>
+</html>
index a7fa438..a221b7a 100644 (file)
@@ -362,6 +362,7 @@ sputnik/Unicode/Unicode_218/S7.6_A5.2_T1.html
 ### START OF (5) Features that are not supported in WebKit1, so skipped in mac/TestExpectations then re-enabled here
 
 platform/mac/tiled-drawing/ [ Pass ]
+fast/css/sticky/sticky-top-zoomed.html [ Pass ]
 
 ### END OF (5) Features that are not supported in WebKit1, so skipped in mac/TestExpectations then re-enabled here
 ########################################
index f756e7d..7ab6965 100644 (file)
@@ -1216,6 +1216,9 @@ webkit.org/b/61138 http/tests/w3c/webperf/submission/Intel/resource-timing [ Ski
 # TileCache tests that don't apply to WK1 (they are re-enabled via the WK2 TestExpectations file)
 platform/mac/tiled-drawing/ [ Skip ]
 
+# Can't hide scrollbars in WK1
+fast/css/sticky/sticky-top-zoomed.html [ ImageOnlyFailure ]
+
 webkit.org/b/100846 inspector-protocol/debugger-pause-dedicated-worker.html [ Skip ]
 webkit.org/b/100846 inspector-protocol/debugger-terminate-dedicated-worker-while-paused.html [ Skip ]
 
index 3be2740..d53af4e 100644 (file)
@@ -1,3 +1,25 @@
+2012-12-17  Simon Fraser  <simon.fraser@apple.com>
+
+        Fix position:-webkit-sticky behavior when zoomed
+        https://bugs.webkit.org/show_bug.cgi?id=105251
+
+        Reviewed by Dean Jackson.
+
+        Position sticky elements were misplaced when stickily-constrained, under zooming.
+        The cause was that some of the functions used to compute sticky position
+        took page scale into account, and some did not.
+        
+        Fix by using localToContainerQuad(..., view()) to compute RenderView-relative
+        quads, which avoids page scale, so all the constraints math is done ignoring
+        page scale. This also requires that we compute a scale-free viewport rect
+        in stickyPositionOffset().
+
+        Test: fast/css/sticky/sticky-top-zoomed.html
+
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::computeStickyPositionConstraints):
+        (WebCore::RenderBoxModelObject::stickyPositionOffset):
+
 2012-12-18  Eugene Klyuchnikov  <eustas@chromium.org>
 
         Web Inspector: DataGrid cell values are "clipped" in editing mode.
index 0b7d771..67b3241 100644 (file)
@@ -471,7 +471,8 @@ void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
     // Compute the container-relative area within which the sticky element is allowed to move.
     containerContentRect.move(minLeftMargin, minTopMargin);
     containerContentRect.contract(minLeftMargin + minRightMargin, minTopMargin + minBottomMargin);
-    constraints.setAbsoluteContainingBlockRect(containingBlock->localToAbsoluteQuad(FloatRect(containerContentRect)).boundingBox());
+    // Map to the view to avoid including page scale factor.
+    constraints.setAbsoluteContainingBlockRect(containingBlock->localToContainerQuad(FloatRect(containerContentRect), view()).boundingBox());
 
     LayoutRect stickyBoxRect = frameRectForStickyPositioning();
     LayoutRect flippedStickyBoxRect = stickyBoxRect;
@@ -479,7 +480,9 @@ void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
     LayoutPoint stickyLocation = flippedStickyBoxRect.location();
 
     // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms.
-    FloatRect absContainerFrame = containingBlock->localToAbsoluteQuad(FloatRect(FloatPoint(), containingBlock->size())).boundingBox();
+    // Map to the view to avoid including page scale factor.
+    FloatRect absContainerFrame = containingBlock->localToContainerQuad(FloatRect(FloatPoint(), containingBlock->size()), view()).boundingBox();
+
     // We can't call localToAbsolute on |this| because that will recur. FIXME: For now, assume that |this| is not transformed.
     FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocation, flippedStickyBoxRect.size());
     constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect);
@@ -508,7 +511,12 @@ void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
 LayoutSize RenderBoxModelObject::stickyPositionOffset() const
 {
     LayoutRect viewportRect = view()->frameView()->visibleContentRect();
-
+    float scale = 1;
+    if (Frame* frame = view()->frameView()->frame())
+        scale = frame->frameScaleFactor();
+    
+    viewportRect.scale(1 / scale);
+    
     StickyPositionViewportConstraints constraints;
     computeStickyPositionConstraints(constraints, viewportRect);