Bug 1145968 - [css-grid] Make grid items paint as inline-blocks and create a stacking context when 'z-index' != 'auto'. r=dholbert
authorMats Palmgren <mats@mozilla.com>
Thu, 26 Mar 2015 18:57:39 +0000
changeset 264821 13f447b5f8c2d960551fd855670ea77a5733fff9
parent 264820 a55d25db977892b42460a17ce3a305a385ba3d86
child 264822 b41915b3c38be487eb54742253341e7a11ea31b1
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1145968
milestone39.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 1145968 - [css-grid] Make grid items paint as inline-blocks and create a stacking context when 'z-index' != 'auto'. r=dholbert
layout/generic/nsGridContainerFrame.cpp
layout/generic/nsGridContainerFrame.h
layout/reftests/css-grid/grid-placement-definite-002-ref.html
layout/reftests/css-grid/grid-placement-definite-002.html
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -8,16 +8,17 @@
 
 #include "nsGridContainerFrame.h"
 
 #include "mozilla/Maybe.h"
 #include "nsAbsoluteContainingBlock.h"
 #include "nsAlgorithm.h" // for clamped()
 #include "nsCSSAnonBoxes.h"
 #include "nsDataHashtable.h"
+#include "nsDisplayList.h"
 #include "nsHashKeys.h"
 #include "nsIFrameInlines.h"
 #include "nsPresContext.h"
 #include "nsReadableUtils.h"
 #include "nsRuleNode.h"
 #include "nsStyleContext.h"
 
 using namespace mozilla;
@@ -157,16 +158,36 @@ GridLinePosition(uint32_t aLine, const n
   MOZ_ASSERT(endIndex <= aTrackSizes.Length(), "aTrackSizes is too small");
   nscoord pos = 0;
   for (uint32_t i = 0; i < endIndex; ++i) {
     pos += aTrackSizes[i].mBase;
   }
   return pos;
 }
 
+/**
+ * (XXX share this utility function with nsFlexContainerFrame at some point)
+ *
+ * Helper for BuildDisplayList, to implement this special-case for grid
+ * items from the spec:
+ *   The painting order of grid items is exactly the same as inline blocks,
+ *   except that [...] 'z-index' values other than 'auto' create a stacking
+ *   context even if 'position' is 'static'.
+ * http://dev.w3.org/csswg/css-grid/#z-order
+ */
+static uint32_t
+GetDisplayFlagsForGridItem(nsIFrame* aFrame)
+{
+  const nsStylePosition* pos = aFrame->StylePosition();
+  if (pos->mZIndex.GetUnit() == eStyleUnit_Integer) {
+    return nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT;
+  }
+  return nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT;
+}
+
 //----------------------------------------------------------------------
 
 // Frame class boilerplate
 // =======================
 
 NS_QUERYFRAME_HEAD(nsGridContainerFrame)
   NS_QUERYFRAME_ENTRY(nsGridContainerFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
@@ -1103,16 +1124,34 @@ nsGridContainerFrame::Reflow(nsPresConte
 }
 
 nsIAtom*
 nsGridContainerFrame::GetType() const
 {
   return nsGkAtoms::gridContainerFrame;
 }
 
+void
+nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                       const nsRect&           aDirtyRect,
+                                       const nsDisplayListSet& aLists)
+{
+  DisplayBorderBackgroundOutline(aBuilder, aLists);
+
+  // Our children are all grid-level boxes, which behave the same as
+  // inline-blocks in painting, so their borders/backgrounds all go on
+  // the BlockBorderBackgrounds list.
+  nsDisplayListSet childLists(aLists, aLists.BlockBorderBackgrounds());
+  for (nsFrameList::Enumerator e(PrincipalChildList()); !e.AtEnd(); e.Next()) {
+    nsIFrame* child = e.get();
+    BuildDisplayListForChild(aBuilder, child, aDirtyRect, childLists,
+                             ::GetDisplayFlagsForGridItem(child));
+  }
+}
+
 #ifdef DEBUG_FRAME_DUMP
 nsresult
 nsGridContainerFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("GridContainer"), aResult);
 }
 #endif
 
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -29,16 +29,20 @@ public:
 
   // nsIFrame overrides
   void Reflow(nsPresContext*           aPresContext,
               nsHTMLReflowMetrics&     aDesiredSize,
               const nsHTMLReflowState& aReflowState,
               nsReflowStatus&          aStatus) override;
   virtual nsIAtom* GetType() const override;
 
+  void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                        const nsRect&           aDirtyRect,
+                        const nsDisplayListSet& aLists) override;
+
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   /**
    * Return the containing block for aChild which MUST be an abs.pos. child
    * of a grid container.  This is just a helper method for
    * nsAbsoluteContainingBlock::Reflow - it's not meant to be used elsewhere.
--- a/layout/reftests/css-grid/grid-placement-definite-002-ref.html
+++ b/layout/reftests/css-grid/grid-placement-definite-002-ref.html
@@ -1,13 +1,17 @@
 <!DOCTYPE HTML>
 <html><head>
     <meta charset="utf-8">
     <title></title>
     <style type="text/css">
+html,body {
+  font-size:16px;
+  font-family:monospace;
+}
 .grid {
   height: 60px;
   border: 1px solid green;
   position: relative;
 }
 
 span {
   position: absolute;
@@ -65,16 +69,24 @@ span {
 
 .test6 span {
   top: 0;
   left: 0;
   width: 20px;
   height: 20px;
 }
 
+.test7 span {
+  top: 0;
+  left: 0;
+  width: 700px;
+  height: 60px;
+  padding:3px;
+}
+
     </style>
 </head>
 <body>
 
 <div class="grid test1"><span>a</span></div>
 
 <div class="grid test2">
 <span class="a">a</span>
@@ -85,10 +97,12 @@ span {
 <div class="grid test3"><span>a</span></div>
 
 <div class="grid test4"><span>a</span></div>
 
 <div class="grid test5"><span>a</span></div>
 
 <div class="grid test6"><span>b</span></div>
 
+<div class="grid test7"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;grid</span></div>
+
 </body>
 </html>
--- a/layout/reftests/css-grid/grid-placement-definite-002.html
+++ b/layout/reftests/css-grid/grid-placement-definite-002.html
@@ -1,13 +1,17 @@
 <!DOCTYPE HTML>
 <html><head>
     <meta charset="utf-8">
     <title></title>
     <style type="text/css">
+html,body {
+  font-size:16px;
+  font-family:monospace;
+}
 .grid {
   display: grid;
   border: 1px solid green;
   grid-template-columns: 20px 20px 20px 20px;
   grid-template-rows: 20px 20px 20px;
   grid-auto-flow: row;
   grid-auto-columns: 20px;
   grid-auto-rows: 20px;
@@ -51,16 +55,19 @@ span {
   grid-template-columns: 20px (a-start) 20px (a-start) 20px (a-end) 20px ;
 }
 .test4 span { grid-column: a-start 2 / 8; }
 .test5 span { grid-column: a / 8; }
 
 .test6 #span1 { grid-row:1/2; grid-column:1/2; }
 .test6 #span2 { grid-row:1/2; grid-column: non-existent / span 1; }
 
+.test7 {grid-template-columns: 700px; grid-template-rows: 60px; }
+.test7 #span1 { grid-area: 1/1; background: red;  border: 4px solid red; color:red; }
+.test7 #span2 { grid-area: 1/1; background: lime; padding: 3px; margin:0; }
 
     </style>
 </head>
 <body>
 
 <div class="grid test1"><span>a</span></div>
 
 <div class="grid test2">
@@ -72,10 +79,12 @@ span {
 <div class="grid test3"><span>a</span></div>
 
 <div class="grid test4"><span>a</span></div>
 
 <div class="grid test5"><span>a</span></div>
 
 <div class="grid test6"><span id="span1">a</span><span id="span2">b</span></div>
 
+<div class="grid test7"><span id="span1">FAIL</span><span id="span2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;grid</span></div>
+
 </body>
 </html>