Bug 984869 - Add support for display:flex/grid and columnset layout to <button>. r=tn
authorMats Palmgren <mats@mozilla.com>
Thu, 06 Oct 2016 22:43:22 +0200
changeset 316850 40fb8eae281b54d28253cf94fe31df8aae92881c
parent 316849 32aa05912bbb3f1efc7d63f54417e62c46953947
child 316851 1e3af7fd9bfe507cdcff5e05a95c3a763617f25c
push id32932
push userphilringnalda@gmail.com
push dateFri, 07 Oct 2016 03:24:25 +0000
treeherderautoland@7affb66131bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs984869
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 984869 - Add support for display:flex/grid and columnset layout to <button>. r=tn
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFlexContainerFrame.cpp
layout/style/res/forms.css
layout/style/res/ua.css
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3874,44 +3874,78 @@ nsCSSFrameConstructor::ConstructFrameFro
 
     // If we need to create a block formatting context to wrap our
     // kids, do it now.
     const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
     nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
     nsIFrame* maybeAbsoluteContainingBlock = newFrame;
     nsIFrame* possiblyLeafFrame = newFrame;
     if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
-      RefPtr<nsStyleContext> blockContext;
-      blockContext =
+      RefPtr<nsStyleContext> outerSC =
         mPresShell->StyleSet()->ResolveAnonymousBoxStyle(*data->mAnonBoxPseudo,
                                                          styleContext);
-      nsIFrame* blockFrame =
-        NS_NewBlockFormattingContext(mPresShell, blockContext);
-
 #ifdef DEBUG
       nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
       MOZ_ASSERT(containerFrame);
 #endif
       nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
-      InitAndRestoreFrame(aState, content, container, blockFrame);
-
-      SetInitialSingleChild(container, blockFrame);
-
-      // Now figure out whether newFrame or blockFrame should be the
-      // absolute container.  It should be the latter if it's
-      // positioned, otherwise the former.
-      const nsStyleDisplay* blockDisplay = blockContext->StyleDisplay();
-      if (blockDisplay->IsAbsPosContainingBlock(blockFrame)) {
-        maybeAbsoluteContainingBlockDisplay = blockDisplay;
-        maybeAbsoluteContainingBlock = blockFrame;
-        maybeAbsoluteContainingBlockStyleFrame = blockFrame;
-      }
-
-      // Our kids should go into the blockFrame
-      newFrame = blockFrame;
+      nsContainerFrame* outerFrame;
+      nsContainerFrame* innerFrame;
+      switch (display->mDisplay) {
+        case StyleDisplay::Flex:
+        case StyleDisplay::InlineFlex:
+          outerFrame = NS_NewFlexContainerFrame(mPresShell, outerSC);
+          InitAndRestoreFrame(aState, content, container, outerFrame);
+          innerFrame = outerFrame;
+          break;
+        case StyleDisplay::Grid:
+        case StyleDisplay::InlineGrid:
+          outerFrame = NS_NewGridContainerFrame(mPresShell, outerSC);
+          InitAndRestoreFrame(aState, content, container, outerFrame);
+          innerFrame = outerFrame;
+          break;
+        default: {
+          nsContainerFrame* columnSetFrame = nullptr;
+          RefPtr<nsStyleContext> innerSC = outerSC;
+          const nsStyleColumn* columns = outerSC->StyleColumn();
+          if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
+              columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
+            columnSetFrame =
+              NS_NewColumnSetFrame(mPresShell, outerSC, nsFrameState(0));
+            InitAndRestoreFrame(aState, content, container, columnSetFrame);
+            innerSC = mPresShell->StyleSet()->ResolveAnonymousBoxStyle(
+              nsCSSAnonBoxes::columnContent, outerSC);
+          }
+          innerFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
+          if (columnSetFrame) {
+            InitAndRestoreFrame(aState, content, columnSetFrame, innerFrame);
+            SetInitialSingleChild(columnSetFrame, innerFrame);
+            outerFrame = columnSetFrame;
+          } else {
+            InitAndRestoreFrame(aState, content, container, innerFrame);
+            outerFrame = innerFrame;
+          }
+          break;
+        }
+      }
+
+      SetInitialSingleChild(container, outerFrame);
+
+      // Now figure out whether newFrame or outerFrame should be the
+      // absolute container.
+      auto outerDisplay = outerSC->StyleDisplay();
+      if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
+        maybeAbsoluteContainingBlockDisplay = outerDisplay;
+        maybeAbsoluteContainingBlock = outerFrame;
+        maybeAbsoluteContainingBlockStyleFrame = outerFrame;
+        innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
+      }
+
+      // Our kids should go into the innerFrame.
+      newFrame = innerFrame;
     }
 
     aState.AddChild(frameToAddToList, aFrameItems, content, styleContext,
                     aParentFrame, allowOutOfFlow, allowOutOfFlow, isPopup);
 
     nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
     if (newFrameAsContainer) {
 #ifdef MOZ_XUL
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -101,19 +101,21 @@ IsLegacyBox(const nsStyleDisplay* aStyle
   }
 
   // If this frame is for a scrollable element, then it will actually have
   // "display:block", and its *parent* will have the real flex-flavored display
   // value. So in that case, check the parent to find out if we're legacy.
   if (aStyleDisp->mDisplay == mozilla::StyleDisplay::Block) {
     nsStyleContext* parentStyleContext = aStyleContext->GetParent();
     NS_ASSERTION(parentStyleContext &&
-                 aStyleContext->GetPseudo() == nsCSSAnonBoxes::scrolledContent,
+                 (aStyleContext->GetPseudo() == nsCSSAnonBoxes::buttonContent ||
+                  aStyleContext->GetPseudo() == nsCSSAnonBoxes::scrolledContent),
                  "The only way a nsFlexContainerFrame can have 'display:block' "
-                 "should be if it's the inner part of a scrollable element");
+                 "should be if it's the inner part of a scrollable or button "
+                 "element");
     if (IsDisplayValueLegacyBox(parentStyleContext->StyleDisplay())) {
       return true;
     }
   }
 
   return false;
 }
 
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -14,17 +14,17 @@
   display: block; /* nsRuleNode::ComputeDisplayData overrules this in some cases */
   unicode-bidi: inherit;
   text-overflow: inherit;
   overflow: inherit;
   overflow-clip-box: inherit;
   padding: inherit;
   block-size: 100%; /* Need this so percentage block-sizes of kids work right */
   /* Please keep the Multicol/Flex/Grid/Align sections below in sync with
-     ::-moz-scrolled-content in ua.css */
+     ::-moz-scrolled-content in ua.css and ::-moz-button-content below. */
   /* Multicol container */
   -moz-column-count: inherit;
   -moz-column-width: inherit;
   -moz-column-gap: inherit;
   -moz-column-rule: inherit;
   -moz-column-fill: inherit;
   /* Flex container */
   flex-direction: inherit;
@@ -656,16 +656,41 @@ button {
   white-space: inherit;
   text-indent: 0;
   /* But no text-decoration reaching inside, by default */
   display: inline-block;
 }
 
 *|*::-moz-button-content {
   display: block;
+  /* Please keep the Multicol/Flex/Grid/Align sections below in sync with
+     ::-moz-scrolled-content in ua.css and ::-moz-fieldset-content above. */
+  /* Multicol container */
+  -moz-column-count: inherit;
+  -moz-column-width: inherit;
+  -moz-column-gap: inherit;
+  -moz-column-rule: inherit;
+  -moz-column-fill: inherit;
+  /* Flex container */
+  flex-direction: inherit;
+  flex-wrap: inherit;
+  /* Grid container */
+  grid-auto-columns: inherit;
+  grid-auto-rows: inherit;
+  grid-auto-flow: inherit;
+  grid-column-gap: inherit;
+  grid-row-gap: inherit;
+  grid-template-areas: inherit;
+  grid-template-columns: inherit;
+  grid-template-rows: inherit;
+  /* CSS Align */
+  align-content: inherit;
+  align-items: inherit;
+  justify-content: inherit;
+  justify-items: inherit;
 }
 
 button:hover,
 input[type="color"]:-moz-system-metric(color-picker-available):hover,
 input[type="reset"]:hover,
 input[type="button"]:hover,
 input[type="submit"]:hover {
   background-color: -moz-buttonhoverface;
--- a/layout/style/res/ua.css
+++ b/layout/style/res/ua.css
@@ -166,17 +166,17 @@
      affects auto-width sizing of the block we create. */
   display: block;
   -moz-box-orient: inherit;
   /* make unicode-bidi inherit, otherwise it has no effect on text inputs and
      blocks with overflow: scroll; */
   unicode-bidi: inherit;
   text-overflow: inherit;
   /* Please keep the Multicol/Flex/Grid/Align sections below in sync with
-     ::-moz-fieldset-content in forms.css */
+     ::-moz-fieldset-content/::-moz-button-content in forms.css */
   /* Multicol container */
   -moz-column-count: inherit;
   -moz-column-width: inherit;
   -moz-column-gap: inherit;
   -moz-column-rule: inherit;
   -moz-column-fill: inherit;
   /* Flex container */
   flex-direction: inherit;