support overflow:auto and overflow:scroll in new flexbox
authortony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jan 2012 19:27:54 +0000 (19:27 +0000)
committertony@chromium.org <tony@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jan 2012 19:27:54 +0000 (19:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=76953

Reviewed by David Hyatt.

Source/WebCore:

Tests: css3/flexbox/flexbox-overflow-auto-expected.html
       css3/flexbox/flexbox-overflow-auto.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::addLayoutOverflow): In the case of reverse flexboxen, we can overflow up or to the left (like horizontal-bt or rtl content).
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::layoutBlock): Call updateScrollInfoAfterLayout() to add overflow scrollbars.
(WebCore::RenderFlexibleBox::layoutAndPlaceChildren): In row-reverse, offset the start of the content by the scrollbar.
(WebCore::RenderFlexibleBox::layoutColumnReverse): In column-reverse, offset the start of the content by the scrollbar.
* rendering/RenderFlexibleBox.h:
(RenderFlexibleBox): Make isHorizontalFlow public.
* rendering/style/RenderStyle.h:
(WebCore::RenderStyleBitfields::isReverseFlexDirection): Convenience method.

LayoutTests:

* css3/flexbox/flexbox-overflow-auto-expected.html: Added.
* css3/flexbox/flexbox-overflow-auto.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/css3/flexbox/flexbox-overflow-auto-expected.html [new file with mode: 0644]
LayoutTests/css3/flexbox/flexbox-overflow-auto.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.cpp
Source/WebCore/rendering/RenderFlexibleBox.h
Source/WebCore/rendering/style/RenderStyle.h

index bb26584..bdbc1d9 100644 (file)
@@ -1,3 +1,13 @@
+2012-01-25  Tony Chang  <tony@chromium.org>
+
+        support overflow:auto and overflow:scroll in new flexbox
+        https://bugs.webkit.org/show_bug.cgi?id=76953
+
+        Reviewed by David Hyatt.
+
+        * css3/flexbox/flexbox-overflow-auto-expected.html: Added.
+        * css3/flexbox/flexbox-overflow-auto.html: Added.
+
 2012-01-25  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r105885.
diff --git a/LayoutTests/css3/flexbox/flexbox-overflow-auto-expected.html b/LayoutTests/css3/flexbox/flexbox-overflow-auto-expected.html
new file mode 100644 (file)
index 0000000..0a5024b
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.test-row {
+    display: -webkit-flexbox;
+    margin-bottom: 5px;
+}
+
+.container {
+    margin-right: 5px;
+    border: 5px solid lightgreen;
+    width: 100px;
+}
+
+.flexbox {
+    display: block;
+    height: 100px;
+    width: 100px;
+    overflow: auto;
+}
+
+.flexbox > div {
+    width: 200px;
+    height: 200px;
+    background: -webkit-radial-gradient(center, ellipse cover, rgba(30,87,153,1) 0%,rgba(89,148,202,1) 62%,rgba(95,154,207,0.7) 68%,rgba(125,185,232,0) 100%);
+}
+</style>
+</head>
+<body>
+    <p>Scrollbars should work in all the flexboxes.</p>
+</body>
+<script>
+// The -almost values are cases where we don't scroll all the way because of
+// https://bugs.webkit.org/show_bug.cgi?id=76129 .
+var results = [
+    'left top', 'left top', 'right top', 'left bottom',
+    'left bottom-almost', 'left bottom-almost', 'right bottom-almost', 'left top',
+    'right-almost top', 'right-almost top', 'right-almost bottom', 'left top',
+    'left top', 'left top', 'left bottom', 'right top'];
+
+var testContents = '';
+for (var i = 0; i < results.length; ++i) {
+    if (!(i % 4))
+        testContents += "<div class='test-row'>";
+
+    var containerClass = 'container ' + results[i];
+    testContents +=
+        "<div class='" + containerClass + "'>" +
+        "<div class='flexbox'>" +
+        "<div></div>" +
+        "</div>" +
+        "</div>";
+    if (i % 4 == 3)
+        testContents += "</div>";
+}
+
+document.body.innerHTML += testContents;
+
+Array.prototype.forEach.call(document.querySelectorAll(".right"), function(element) {
+    element.firstChild.scrollLeft = 1000;
+});
+
+Array.prototype.forEach.call(document.querySelectorAll(".bottom"), function(element) {
+    element.firstChild.scrollTop = 1000;
+});
+
+Array.prototype.forEach.call(document.querySelectorAll(".right-almost"), function(element) {
+    element.firstChild.scrollLeft = element.firstChild.scrollWidth - element.firstChild.offsetWidth;
+});
+
+Array.prototype.forEach.call(document.querySelectorAll(".bottom-almost"), function(element) {
+    element.firstChild.scrollTop = element.firstChild.scrollHeight - element.firstChild.offsetHeight;
+});
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/css3/flexbox/flexbox-overflow-auto.html b/LayoutTests/css3/flexbox/flexbox-overflow-auto.html
new file mode 100644 (file)
index 0000000..f893f70
--- /dev/null
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.test-row {
+    display: -webkit-flexbox;
+    margin-bottom: 5px;
+}
+
+.container {
+    margin-right: 5px;
+    border: 5px solid lightgreen;
+    width: 100px;
+}
+
+.horizontal-tb {
+    -webkit-writing-mode: horizontal-tb;
+}
+
+.horizontal-bt {
+    -webkit-writing-mode: horizontal-bt;
+}
+
+.vertical-rl {
+    -webkit-writing-mode: vertical-rl;
+}
+
+.vertical-lr {
+    -webkit-writing-mode: vertical-lr;
+}
+
+.row {
+    -webkit-flex-direction: row;
+}
+
+.row-reverse {
+    -webkit-flex-direction: row-reverse;
+}
+
+.column {
+    -webkit-flex-direction: column;
+}
+
+.column-reverse {
+    -webkit-flex-direction: column-reverse;
+}
+
+.flexbox {
+    border: 0 solid pink;
+    display: -webkit-flexbox;
+    height: 100px;
+    width: 100px;
+    overflow: auto;
+}
+
+.flexbox > div {
+    width: 200px;
+    height: 200px;
+    background: -webkit-radial-gradient(center, ellipse cover, rgba(30,87,153,1) 0%,rgba(89,148,202,1) 62%,rgba(95,154,207,0.7) 68%,rgba(125,185,232,0) 100%);
+}
+
+</style>
+</head>
+<body>
+    <p>Scrollbars should work in all the flexboxes.</p>
+</body>
+<script>
+var writingModes = ['horizontal-tb', 'horizontal-bt', 'vertical-rl', 'vertical-lr'];
+var flexDirections = ['row', 'column', 'row-reverse', 'column-reverse'];
+var testContents = '';
+writingModes.forEach(function(writingMode) {
+    testContents += "<div class='test-row'>";
+    flexDirections.forEach(function(flexDirection) {
+        var containerClass = 'container ' + writingMode;
+        var flexboxClass = 'flexbox ' + flexDirection;
+        testContents +=
+            "<div class='" + containerClass + "'>" +
+            "<div class='" + flexboxClass + "'>" +
+            "<div></div>" +
+            "</div>" +
+            "</div>";
+    });
+    testContents += "</div>";
+});
+
+document.body.innerHTML += testContents;
+
+</script>
+</body>
+</html>
index 13b0e97..63f3a4c 100644 (file)
@@ -1,3 +1,24 @@
+2012-01-25  Tony Chang  <tony@chromium.org>
+
+        support overflow:auto and overflow:scroll in new flexbox
+        https://bugs.webkit.org/show_bug.cgi?id=76953
+
+        Reviewed by David Hyatt.
+
+        Tests: css3/flexbox/flexbox-overflow-auto-expected.html
+               css3/flexbox/flexbox-overflow-auto.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::addLayoutOverflow): In the case of reverse flexboxen, we can overflow up or to the left (like horizontal-bt or rtl content).
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::layoutBlock): Call updateScrollInfoAfterLayout() to add overflow scrollbars.
+        (WebCore::RenderFlexibleBox::layoutAndPlaceChildren): In row-reverse, offset the start of the content by the scrollbar.
+        (WebCore::RenderFlexibleBox::layoutColumnReverse): In column-reverse, offset the start of the content by the scrollbar.
+        * rendering/RenderFlexibleBox.h:
+        (RenderFlexibleBox): Make isHorizontalFlow public.
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyleBitfields::isReverseFlexDirection): Convenience method.
+
 2012-01-25  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r105885.
index a89b14d..2e2e215 100644 (file)
@@ -42,6 +42,7 @@
 #include "PaintInfo.h"
 #include "RenderArena.h"
 #include "RenderBoxRegionInfo.h"
+#include "RenderFlexibleBox.h"
 #include "RenderFlowThread.h"
 #include "RenderInline.h"
 #include "RenderLayer.h"
@@ -3593,6 +3594,13 @@ void RenderBox::addLayoutOverflow(const LayoutRect& rect)
         // and vertical-lr/rl as the same.
         bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode();
         bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode();
+        if (isFlexibleBox() && style()->isReverseFlexDirection()) {
+            RenderFlexibleBox* flexibleBox = static_cast<RenderFlexibleBox*>(this);
+            if (flexibleBox->isHorizontalFlow())
+                hasLeftOverflow = true;
+            else
+                hasTopOverflow = true;
+        }
         
         if (!hasTopOverflow)
             overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
index 21bd9bd..13a15d6 100644 (file)
@@ -175,6 +175,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
 
     m_overflow.clear();
 
+    // For overflow:scroll blocks, ensure we have both scrollbars in place always.
+    if (scrollsOverflow()) {
+        if (style()->overflowX() == OSCROLL)
+            layer()->setHasHorizontalScrollbar(true);
+        if (style()->overflowY() == OSCROLL)
+            layer()->setHasVerticalScrollbar(true);
+    }
+
     layoutFlexItems(relayoutChildren);
 
     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
@@ -191,6 +199,11 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int, BlockLayoutPass)
 
     updateLayerTransform();
 
+    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    if (hasOverflowClip())
+        layer()->updateScrollInfoAfterLayout();
+
     repainter.repaintAfterLayout();
 
     setNeedsLayout(false);
@@ -636,6 +649,8 @@ void RenderFlexibleBox::layoutAndPlaceChildren(FlexOrderIterator& iterator, cons
 {
     LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
     mainAxisOffset += initialPackingOffset(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size());
+    if (style()->flexDirection() == FlowRowReverse)
+        mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
 
     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
     LayoutUnit totalMainExtent = mainAxisExtent();
@@ -699,6 +714,7 @@ void RenderFlexibleBox::layoutColumnReverse(FlexOrderIterator& iterator, const W
     // just moving the children to a new position.
     LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd();
     mainAxisOffset -= initialPackingOffset(availableFreeSpace, totalPositiveFlexibility, style()->flexPack(), childSizes.size());
+    mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
 
     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
     size_t i = 0;
index fd8a311..f73ded7 100644 (file)
@@ -46,6 +46,8 @@ public:
 
     virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass);
 
+    bool isHorizontalFlow() const;
+
 private:
     class TreeOrderIterator;
     class FlexOrderIterator;
@@ -53,7 +55,6 @@ private:
 
     bool hasOrthogonalFlow(RenderBox* child) const;
     bool isColumnFlow() const;
-    bool isHorizontalFlow() const;
     bool isLeftToRightFlow() const;
     Length crossAxisLength() const;
     Length mainAxisLengthForChild(RenderBox* child) const;
index 2b057d3..74fae1d 100644 (file)
@@ -808,6 +808,7 @@ public:
     EFlexAlign flexItemAlign() const { return static_cast<EFlexAlign>(rareNonInheritedData->m_flexibleBox->m_flexItemAlign); }
     EFlexDirection flexDirection() const { return static_cast<EFlexDirection>(rareNonInheritedData->m_flexibleBox->m_flexDirection); }
     bool isColumnFlexDirection() const { return flexDirection() == FlowColumn || flexDirection() == FlowColumnReverse; }
+    bool isReverseFlexDirection() const { return flexDirection() == FlowRowReverse || flexDirection() == FlowColumnReverse; }
     EFlexWrap flexWrap() const { return static_cast<EFlexWrap>(rareNonInheritedData->m_flexibleBox->m_flexWrap); }
 
 #if ENABLE(CSS_GRID_LAYOUT)