| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/compositing/CompositedLayerMapping.h" | 5 #include "core/layout/compositing/CompositedLayerMapping.h" |
| 6 | 6 |
| 7 #include "core/frame/LocalFrameView.h" | 7 #include "core/frame/LocalFrameView.h" |
| 8 #include "core/layout/LayoutBoxModelObject.h" | 8 #include "core/layout/LayoutBoxModelObject.h" |
| 9 #include "core/layout/LayoutTestHelper.h" | 9 #include "core/layout/LayoutTestHelper.h" |
| 10 #include "core/layout/api/LayoutViewItem.h" | 10 #include "core/layout/api/LayoutViewItem.h" |
| (...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 ToLayoutBoxModelObject(child->GetLayoutObject())->Layer(); | 1469 ToLayoutBoxModelObject(child->GetLayoutObject())->Layer(); |
| 1470 ASSERT_TRUE(child_paint_layer); | 1470 ASSERT_TRUE(child_paint_layer); |
| 1471 CompositedLayerMapping* child_mapping = | 1471 CompositedLayerMapping* child_mapping = |
| 1472 child_paint_layer->GetCompositedLayerMapping(); | 1472 child_paint_layer->GetCompositedLayerMapping(); |
| 1473 ASSERT_TRUE(child_mapping); | 1473 ASSERT_TRUE(child_mapping); |
| 1474 EXPECT_TRUE(child_mapping->AncestorClippingLayer()); | 1474 EXPECT_TRUE(child_mapping->AncestorClippingLayer()); |
| 1475 EXPECT_FALSE(child_mapping->AncestorClippingLayer()->MaskLayer()); | 1475 EXPECT_FALSE(child_mapping->AncestorClippingLayer()->MaskLayer()); |
| 1476 EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer()); | 1476 EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer()); |
| 1477 } | 1477 } |
| 1478 | 1478 |
| 1479 TEST_P(CompositedLayerMappingTest, StickyPositionContentOffset) { | 1479 TEST_P(CompositedLayerMappingTest, StickyPositionMainThreadOffset) { |
| 1480 SetBodyInnerHTML( | |
| 1481 "<div style='width: 400px; height: 400px; overflow: auto; " | |
| 1482 "will-change: transform;' >" | |
| 1483 " <div id='sticky1' style='position: sticky; top: 0px; width: 100px; " | |
| 1484 "height: 100px; box-shadow: -5px -5px 5px 0 black; " | |
| 1485 "will-change: transform;'></div>" | |
| 1486 " <div style='height: 2000px;'></div>" | |
| 1487 "</div>" | |
| 1488 | |
| 1489 "<div style='width: 400px; height: 400px; overflow: auto; " | |
| 1490 "will-change: transform;' >" | |
| 1491 " <div id='sticky2' style='position: sticky; top: 0px; width: 100px; " | |
| 1492 "height: 100px; will-change: transform;'>" | |
| 1493 " <div style='position: absolute; top: -50px; left: -50px; " | |
| 1494 "width: 5px; height: 5px; background: red;'></div></div>" | |
| 1495 " <div style='height: 2000px;'></div>" | |
| 1496 "</div>"); | |
| 1497 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); | |
| 1498 | |
| 1499 CompositedLayerMapping* sticky1 = | |
| 1500 ToLayoutBlock(GetLayoutObjectByElementId("sticky1")) | |
| 1501 ->Layer() | |
| 1502 ->GetCompositedLayerMapping(); | |
| 1503 CompositedLayerMapping* sticky2 = | |
| 1504 ToLayoutBlock(GetLayoutObjectByElementId("sticky2")) | |
| 1505 ->Layer() | |
| 1506 ->GetCompositedLayerMapping(); | |
| 1507 | |
| 1508 // Box offsets the content by the combination of the shadow offset and blur | |
| 1509 // radius plus an additional pixel of anti-aliasing. | |
| 1510 ASSERT_TRUE(sticky1); | |
| 1511 WebLayerStickyPositionConstraint constraint1 = | |
| 1512 sticky1->MainGraphicsLayer() | |
| 1513 ->ContentLayer() | |
| 1514 ->Layer() | |
| 1515 ->StickyPositionConstraint(); | |
| 1516 EXPECT_EQ(IntPoint(-11, -11), | |
| 1517 IntPoint(constraint1.parent_relative_sticky_box_offset)); | |
| 1518 | |
| 1519 // Since the nested div will be squashed into the same composited layer the | |
| 1520 // sticky element is offset by the nested element's offset. | |
| 1521 ASSERT_TRUE(sticky2); | |
| 1522 WebLayerStickyPositionConstraint constraint2 = | |
| 1523 sticky2->MainGraphicsLayer() | |
| 1524 ->ContentLayer() | |
| 1525 ->Layer() | |
| 1526 ->StickyPositionConstraint(); | |
| 1527 EXPECT_EQ(IntPoint(-50, -50), | |
| 1528 IntPoint(constraint2.parent_relative_sticky_box_offset)); | |
| 1529 } | |
| 1530 | |
| 1531 TEST_P(CompositedLayerMappingTest, StickyPositionTableCellContentOffset) { | |
| 1532 SetBodyInnerHTML( | |
| 1533 "<style>body {height: 2000px; width: 2000px;} " | |
| 1534 "td, th { height: 50px; width: 50px; } " | |
| 1535 "table {border: none; }" | |
| 1536 "#scroller { overflow: auto; will-change: transform; height: 50px; }" | |
| 1537 "#sticky { position: sticky; left: 0; will-change: transform; }" | |
| 1538 "</style>" | |
| 1539 "<div id='scroller'><table cellspacing='0' cellpadding='0'>" | |
| 1540 " <thead><tr><td></td></tr></thead>" | |
| 1541 " <tr><td id='sticky'></td></tr>" | |
| 1542 "</table></div>"); | |
| 1543 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); | |
| 1544 | |
| 1545 CompositedLayerMapping* sticky = | |
| 1546 ToLayoutBlock(GetLayoutObjectByElementId("sticky")) | |
| 1547 ->Layer() | |
| 1548 ->GetCompositedLayerMapping(); | |
| 1549 | |
| 1550 ASSERT_TRUE(sticky); | |
| 1551 WebLayerStickyPositionConstraint constraint = | |
| 1552 sticky->MainGraphicsLayer() | |
| 1553 ->ContentLayer() | |
| 1554 ->Layer() | |
| 1555 ->StickyPositionConstraint(); | |
| 1556 EXPECT_EQ(IntPoint(0, 50), | |
| 1557 IntPoint(constraint.parent_relative_sticky_box_offset)); | |
| 1558 } | |
| 1559 | |
| 1560 TEST_P(CompositedLayerMappingTest, StickyPositionEnclosingLayersContentOffset) { | |
| 1561 // Using backface-visibility: hidden causes the scroller to become composited | |
| 1562 // without creating a stacking context. This is important as enclosing layer | |
| 1563 // scroll correction works differently depending on whether you are in a | |
| 1564 // stacking context or not. | |
| 1565 SetBodyInnerHTML( | 1480 SetBodyInnerHTML( |
| 1566 "<style>.composited { backface-visibility: hidden; }" | 1481 "<style>.composited { backface-visibility: hidden; }" |
| 1567 "#scroller { overflow: auto; height: 200px; width: 200px; }" | 1482 "#scroller { overflow: auto; height: 200px; width: 200px; }" |
| 1568 ".container { height: 500px; }" | 1483 ".container { height: 500px; }" |
| 1569 ".innerPadding { height: 10px; }" | 1484 ".innerPadding { height: 10px; }" |
| 1570 "#sticky { position: sticky; top: 25px; height: 50px; }</style>" | 1485 "#sticky { position: sticky; top: 25px; height: 50px; }</style>" |
| 1571 "<div id='scroller' class='composited'>" | 1486 "<div id='scroller' class='composited'>" |
| 1572 " <div class='composited container'>" | 1487 " <div class='composited container'>" |
| 1573 " <div class='composited container'>" | 1488 " <div class='composited container'>" |
| 1574 " <div class='innerPadding'></div>" | 1489 " <div class='innerPadding'></div>" |
| 1575 " <div id='sticky' class='composited'></div>" | 1490 " <div id='sticky' class='composited'></div>" |
| 1576 " </div></div></div>"); | 1491 " </div></div></div>"); |
| 1577 | 1492 |
| 1578 PaintLayer* sticky_layer = | 1493 PaintLayer* sticky_layer = |
| 1579 ToLayoutBox(GetLayoutObjectByElementId("sticky"))->Layer(); | 1494 ToLayoutBox(GetLayoutObjectByElementId("sticky"))->Layer(); |
| 1580 CompositedLayerMapping* sticky_mapping = | 1495 CompositedLayerMapping* sticky_mapping = |
| 1581 sticky_layer->GetCompositedLayerMapping(); | 1496 sticky_layer->GetCompositedLayerMapping(); |
| 1582 ASSERT_TRUE(sticky_mapping); | 1497 ASSERT_TRUE(sticky_mapping); |
| 1498 // Main thread offset for sticky should be "StickyTop - InnerPadding". |
| 1499 EXPECT_EQ(IntPoint(0, 15), IntPoint(sticky_mapping->MainGraphicsLayer() |
| 1500 ->ContentLayer() |
| 1501 ->Layer() |
| 1502 ->OffsetForStickyPosition())); |
| 1583 | 1503 |
| 1584 WebLayerStickyPositionConstraint constraint = | 1504 // Now scroll the page - this should increase the main thread offset. |
| 1585 sticky_mapping->MainGraphicsLayer() | |
| 1586 ->ContentLayer() | |
| 1587 ->Layer() | |
| 1588 ->StickyPositionConstraint(); | |
| 1589 EXPECT_EQ(IntPoint(0, 10), | |
| 1590 IntPoint(constraint.parent_relative_sticky_box_offset)); | |
| 1591 | |
| 1592 // Now scroll the page - this should not affect the parent-relative offset. | |
| 1593 LayoutBoxModelObject* scroller = | 1505 LayoutBoxModelObject* scroller = |
| 1594 ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller")); | 1506 ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller")); |
| 1595 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea(); | 1507 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea(); |
| 1596 scrollable_area->ScrollToAbsolutePosition( | 1508 scrollable_area->ScrollToAbsolutePosition( |
| 1597 FloatPoint(scrollable_area->ScrollPosition().X(), 100)); | 1509 FloatPoint(scrollable_area->ScrollPosition().X(), 100)); |
| 1598 ASSERT_EQ(100.0, scrollable_area->ScrollPosition().Y()); | 1510 ASSERT_EQ(100.0, scrollable_area->ScrollPosition().Y()); |
| 1599 | 1511 |
| 1600 sticky_layer->SetNeedsCompositingInputsUpdate(); | 1512 sticky_layer->SetNeedsCompositingInputsUpdate(); |
| 1601 EXPECT_TRUE(sticky_layer->NeedsCompositingInputsUpdate()); | 1513 EXPECT_TRUE(sticky_layer->NeedsCompositingInputsUpdate()); |
| 1602 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); | 1514 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); |
| 1603 EXPECT_FALSE(sticky_layer->NeedsCompositingInputsUpdate()); | 1515 EXPECT_FALSE(sticky_layer->NeedsCompositingInputsUpdate()); |
| 1604 | 1516 |
| 1605 constraint = sticky_mapping->MainGraphicsLayer() | 1517 EXPECT_EQ(IntPoint(0, 115), IntPoint(sticky_mapping->MainGraphicsLayer() |
| 1606 ->ContentLayer() | 1518 ->ContentLayer() |
| 1607 ->Layer() | 1519 ->Layer() |
| 1608 ->StickyPositionConstraint(); | 1520 ->OffsetForStickyPosition())); |
| 1609 EXPECT_EQ(IntPoint(0, 10), | |
| 1610 IntPoint(constraint.parent_relative_sticky_box_offset)); | |
| 1611 } | |
| 1612 | |
| 1613 TEST_P(CompositedLayerMappingTest, | |
| 1614 StickyPositionEnclosingLayersWithStackingContextContentOffset) { | |
| 1615 // Using will-change: transform causes the scroller to become a stacking | |
| 1616 // context. This changes how its descendant layers interact with it; they no | |
| 1617 // longer have a scrollParent and instead just refer to it only as their | |
| 1618 // ancestorOverflowLayer. | |
| 1619 SetBodyInnerHTML( | |
| 1620 "<style>.composited { will-change: transform; }" | |
| 1621 "#scroller { overflow: auto; height: 200px; width: 200px; }" | |
| 1622 ".container { height: 500px; }" | |
| 1623 ".innerPadding { height: 10px; }" | |
| 1624 "#sticky { position: sticky; top: 25px; height: 50px; }</style>" | |
| 1625 "<div id='scroller' class='composited'>" | |
| 1626 " <div class='composited container'>" | |
| 1627 " <div class='composited container'>" | |
| 1628 " <div class='innerPadding'></div>" | |
| 1629 " <div id='sticky' class='composited'></div>" | |
| 1630 " </div></div></div>"); | |
| 1631 | |
| 1632 PaintLayer* sticky_layer = | |
| 1633 ToLayoutBox(GetLayoutObjectByElementId("sticky"))->Layer(); | |
| 1634 CompositedLayerMapping* sticky_mapping = | |
| 1635 sticky_layer->GetCompositedLayerMapping(); | |
| 1636 ASSERT_TRUE(sticky_mapping); | |
| 1637 | |
| 1638 WebLayerStickyPositionConstraint constraint = | |
| 1639 sticky_mapping->MainGraphicsLayer() | |
| 1640 ->ContentLayer() | |
| 1641 ->Layer() | |
| 1642 ->StickyPositionConstraint(); | |
| 1643 EXPECT_EQ(IntPoint(0, 10), | |
| 1644 IntPoint(constraint.parent_relative_sticky_box_offset)); | |
| 1645 | |
| 1646 // Now scroll the page - this should not affect the parent-relative offset. | |
| 1647 LayoutBoxModelObject* scroller = | |
| 1648 ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller")); | |
| 1649 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea(); | |
| 1650 scrollable_area->ScrollToAbsolutePosition( | |
| 1651 FloatPoint(scrollable_area->ScrollPosition().X(), 100)); | |
| 1652 ASSERT_EQ(100.0, scrollable_area->ScrollPosition().Y()); | |
| 1653 | |
| 1654 sticky_layer->SetNeedsCompositingInputsUpdate(); | |
| 1655 EXPECT_TRUE(sticky_layer->NeedsCompositingInputsUpdate()); | |
| 1656 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); | |
| 1657 EXPECT_FALSE(sticky_layer->NeedsCompositingInputsUpdate()); | |
| 1658 | |
| 1659 constraint = sticky_mapping->MainGraphicsLayer() | |
| 1660 ->ContentLayer() | |
| 1661 ->Layer() | |
| 1662 ->StickyPositionConstraint(); | |
| 1663 EXPECT_EQ(IntPoint(0, 10), | |
| 1664 IntPoint(constraint.parent_relative_sticky_box_offset)); | |
| 1665 } | 1521 } |
| 1666 | 1522 |
| 1667 TEST_P(CompositedLayerMappingTest, StickyPositionNotSquashed) { | 1523 TEST_P(CompositedLayerMappingTest, StickyPositionNotSquashed) { |
| 1668 SetBodyInnerHTML( | 1524 SetBodyInnerHTML( |
| 1669 "<style>" | 1525 "<style>" |
| 1670 "#scroller { overflow: auto; height: 200px; }" | 1526 "#scroller { overflow: auto; height: 200px; }" |
| 1671 "#sticky1, #sticky2, #sticky3 {position: sticky; top: 0; width: 50px;" | 1527 "#sticky1, #sticky2, #sticky3 {position: sticky; top: 0; width: 50px;" |
| 1672 " height: 50px; background: rgba(0, 128, 0, 0.5);}" | 1528 " height: 50px; background: rgba(0, 128, 0, 0.5);}" |
| 1673 "#sticky1 {backface-visibility: hidden;}" | 1529 "#sticky1 {backface-visibility: hidden;}" |
| 1674 ".spacer {height: 2000px;}" | 1530 ".spacer {height: 2000px;}" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1698 GetDocument().View()->UpdateAllLifecyclePhases(); | 1554 GetDocument().View()->UpdateAllLifecyclePhases(); |
| 1699 | 1555 |
| 1700 // Now that sticky2 and sticky3 overlap sticky1 they will be promoted, but | 1556 // Now that sticky2 and sticky3 overlap sticky1 they will be promoted, but |
| 1701 // they should not be squashed into the same layer because they scroll with | 1557 // they should not be squashed into the same layer because they scroll with |
| 1702 // respect to each other. | 1558 // respect to each other. |
| 1703 EXPECT_EQ(kPaintsIntoOwnBacking, sticky1->GetCompositingState()); | 1559 EXPECT_EQ(kPaintsIntoOwnBacking, sticky1->GetCompositingState()); |
| 1704 EXPECT_EQ(kPaintsIntoOwnBacking, sticky2->GetCompositingState()); | 1560 EXPECT_EQ(kPaintsIntoOwnBacking, sticky2->GetCompositingState()); |
| 1705 EXPECT_EQ(kPaintsIntoOwnBacking, sticky3->GetCompositingState()); | 1561 EXPECT_EQ(kPaintsIntoOwnBacking, sticky3->GetCompositingState()); |
| 1706 } | 1562 } |
| 1707 | 1563 |
| 1708 TEST_P(CompositedLayerMappingTest, StickyPositionNestedStickyContentOffset) { | |
| 1709 SetBodyInnerHTML( | |
| 1710 "<style>.composited { will-change: transform; }" | |
| 1711 "#scroller { overflow: auto; height: 200px; width: 200px; }" | |
| 1712 ".container { height: 500px; }" | |
| 1713 "#outerSticky { position: sticky; top: 0; height: 100px; }" | |
| 1714 "#middleSticky { position: sticky; top: 10px; height: 50px; }" | |
| 1715 "#innerSticky { position: sticky; top: 25px; height: 25px; }</style>" | |
| 1716 "<div id='scroller' class='composited'>" | |
| 1717 " <div style='height: 50px'></div>" | |
| 1718 " <div class='composited container'>" | |
| 1719 " <div style='height: 10px;'></div>" | |
| 1720 " <div id='outerSticky' class='composited'>" | |
| 1721 " <div id='middleSticky' class='composited'>" | |
| 1722 " <div style='height: 5px;'></div>" | |
| 1723 " <div id='innerSticky' class='composited'></div>" | |
| 1724 " </div>" | |
| 1725 " </div>" | |
| 1726 " </div>" | |
| 1727 "</div>"); | |
| 1728 | |
| 1729 PaintLayer* outer_sticky = | |
| 1730 ToLayoutBox(GetLayoutObjectByElementId("outerSticky"))->Layer(); | |
| 1731 PaintLayer* middle_sticky = | |
| 1732 ToLayoutBox(GetLayoutObjectByElementId("middleSticky"))->Layer(); | |
| 1733 PaintLayer* inner_sticky = | |
| 1734 ToLayoutBox(GetLayoutObjectByElementId("innerSticky"))->Layer(); | |
| 1735 | |
| 1736 WebLayerStickyPositionConstraint outer_sticky_constraint = | |
| 1737 outer_sticky->GetCompositedLayerMapping() | |
| 1738 ->MainGraphicsLayer() | |
| 1739 ->ContentLayer() | |
| 1740 ->Layer() | |
| 1741 ->StickyPositionConstraint(); | |
| 1742 WebLayerStickyPositionConstraint middle_sticky_constraint = | |
| 1743 middle_sticky->GetCompositedLayerMapping() | |
| 1744 ->MainGraphicsLayer() | |
| 1745 ->ContentLayer() | |
| 1746 ->Layer() | |
| 1747 ->StickyPositionConstraint(); | |
| 1748 WebLayerStickyPositionConstraint inner_sticky_constraint = | |
| 1749 inner_sticky->GetCompositedLayerMapping() | |
| 1750 ->MainGraphicsLayer() | |
| 1751 ->ContentLayer() | |
| 1752 ->Layer() | |
| 1753 ->StickyPositionConstraint(); | |
| 1754 | |
| 1755 EXPECT_EQ( | |
| 1756 IntPoint(0, 10), | |
| 1757 IntPoint(outer_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1758 EXPECT_EQ( | |
| 1759 IntPoint(0, 0), | |
| 1760 IntPoint(middle_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1761 EXPECT_EQ( | |
| 1762 IntPoint(0, 5), | |
| 1763 IntPoint(inner_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1764 | |
| 1765 // Scroll the content to engage the sticky elements. | |
| 1766 LayoutBoxModelObject* scroller = | |
| 1767 ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller")); | |
| 1768 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea(); | |
| 1769 scrollable_area->ScrollToAbsolutePosition( | |
| 1770 FloatPoint(scrollable_area->ScrollPosition().X(), 110)); | |
| 1771 ASSERT_EQ(110.0, scrollable_area->ScrollPosition().Y()); | |
| 1772 | |
| 1773 outer_sticky->SetNeedsCompositingInputsUpdate(); | |
| 1774 middle_sticky->SetNeedsCompositingInputsUpdate(); | |
| 1775 inner_sticky->SetNeedsCompositingInputsUpdate(); | |
| 1776 | |
| 1777 GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling(); | |
| 1778 | |
| 1779 outer_sticky_constraint = outer_sticky->GetCompositedLayerMapping() | |
| 1780 ->MainGraphicsLayer() | |
| 1781 ->ContentLayer() | |
| 1782 ->Layer() | |
| 1783 ->StickyPositionConstraint(); | |
| 1784 middle_sticky_constraint = middle_sticky->GetCompositedLayerMapping() | |
| 1785 ->MainGraphicsLayer() | |
| 1786 ->ContentLayer() | |
| 1787 ->Layer() | |
| 1788 ->StickyPositionConstraint(); | |
| 1789 inner_sticky_constraint = inner_sticky->GetCompositedLayerMapping() | |
| 1790 ->MainGraphicsLayer() | |
| 1791 ->ContentLayer() | |
| 1792 ->Layer() | |
| 1793 ->StickyPositionConstraint(); | |
| 1794 | |
| 1795 // After scrolling and despite ancestor sticky changes, the offset relative to | |
| 1796 // the parent layer should remain constant. | |
| 1797 EXPECT_EQ( | |
| 1798 IntPoint(0, 10), | |
| 1799 IntPoint(outer_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1800 EXPECT_EQ( | |
| 1801 IntPoint(0, 0), | |
| 1802 IntPoint(middle_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1803 EXPECT_EQ( | |
| 1804 IntPoint(0, 5), | |
| 1805 IntPoint(inner_sticky_constraint.parent_relative_sticky_box_offset)); | |
| 1806 } | |
| 1807 | |
| 1808 } // namespace blink | 1564 } // namespace blink |
| OLD | NEW |