Bug 931460. Part 2: Call ApplyRelativePositioning on fieldset legends so that sticky and relative positioning works on them. r=mats
authorRobert O'Callahan <robert@ocallahan.org>
Sat, 23 Nov 2013 22:48:26 +1300
changeset 158180 29f004e4fa778a4fdef5f299b32de7ab57c7ad71
parent 158179 be8c4d516bdae46d3b89c0f4151c2784ab00efcd
child 158181 66eb2c676db24664993b9e2a2a3b10e887526d92
push id25737
push usercbook@mozilla.com
push dateMon, 02 Dec 2013 11:42:38 +0000
treeherdermozilla-central@5b9a4d273114 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs931460
milestone28.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 931460. Part 2: Call ApplyRelativePositioning on fieldset legends so that sticky and relative positioning works on them. r=mats
layout/forms/nsFieldSetFrame.cpp
layout/reftests/forms/fieldset/reftest.list
layout/reftests/forms/fieldset/relpos-legend-1-ref.html
layout/reftests/forms/fieldset/relpos-legend-1.html
layout/reftests/forms/fieldset/relpos-legend-2-ref.html
layout/reftests/forms/fieldset/relpos-legend-2.html
layout/reftests/forms/fieldset/sticky-legend-1-ref.html
layout/reftests/forms/fieldset/sticky-legend-1.html
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -12,16 +12,17 @@
 #include "nsPresContext.h"
 #include "RestyleManager.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsDisplayList.h"
 #include "nsRenderingContext.h"
 #include "nsIScrollableFrame.h"
 #include "mozilla/Likely.h"
+#include "mozilla/Maybe.h"
 
 using namespace mozilla;
 using namespace mozilla::layout;
 
 class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -470,23 +471,24 @@ nsFieldSetFrame::Reflow(nsPresContext*  
 
   // get our border and padding
   nsMargin border = aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding;
 
   // Figure out how big the legend is if there is one. 
   // get the legend's margin
   nsMargin legendMargin(0,0,0,0);
   // reflow the legend only if needed
+  Maybe<nsHTMLReflowState> legendReflowState;
+  if (legend) {
+    legendReflowState.construct(aPresContext, aReflowState, legend, availSize);
+  }
   if (reflowLegend) {
-    nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
-                                        legend, availSize);
-
     nsHTMLReflowMetrics legendDesiredSize;
 
-    ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState,
+    ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ref(),
                 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
 #ifdef NOISY_REFLOW
     printf("  returned (%d, %d)\n", legendDesiredSize.width, legendDesiredSize.height);
 #endif
     // figure out the legend's rectangle
     legendMargin = legend->GetUsedMargin();
     mLegendRect.width  = legendDesiredSize.width + legendMargin.left + legendMargin.right;
     mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
@@ -503,17 +505,17 @@ nsFieldSetFrame::Reflow(nsPresContext*  
     }
 
     // if the legend space changes then we need to reflow the 
     // content area as well.
     if (mLegendSpace != oldSpace && inner) {
       reflowInner = true;
     }
 
-    FinishReflowChild(legend, aPresContext, &legendReflowState, 
+    FinishReflowChild(legend, aPresContext, &legendReflowState.ref(), 
                       legendDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME);    
   } else if (!legend) {
     mLegendRect.SetEmpty();
     mLegendSpace = 0;
   } else {
     // mLegendSpace and mLegendRect haven't changed, but we need
     // the used margin when placing the legend.
     legendMargin = legend->GetUsedMargin();
@@ -592,31 +594,25 @@ nsFieldSetFrame::Reflow(nsPresContext*  
           break;
       }
     } else {
       // otherwise make place for the legend
       mLegendRect.x = innerContentRect.x;
       innerContentRect.width = mLegendRect.width;
       contentRect.width = mLegendRect.width + aReflowState.mComputedPadding.LeftRight();
     }
+
     // place the legend
     nsRect actualLegendRect(mLegendRect);
     actualLegendRect.Deflate(legendMargin);
-
-    nsPoint curOrigin = legend->GetPosition();
-
-    // only if the origin changed
-    if ((curOrigin.x != actualLegendRect.x) || (curOrigin.y != actualLegendRect.y)) {
-      legend->SetPosition(nsPoint(actualLegendRect.x , actualLegendRect.y));
-      nsContainerFrame::PositionFrameView(legend);
-
-      // We need to recursively process the legend frame's
-      // children since we're moving the frame after Reflow.
-      nsContainerFrame::PositionChildViews(legend);
-    }
+    nsPoint actualLegendPos(actualLegendRect.TopLeft());
+    legendReflowState.ref().ApplyRelativePositioning(&actualLegendPos);
+    legend->SetPosition(actualLegendPos);
+    nsContainerFrame::PositionFrameView(legend);
+    nsContainerFrame::PositionChildViews(legend);
   }
 
   // Return our size and our result
   if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
     aDesiredSize.height = mLegendSpace + 
                           border.TopBottom() +
                           (inner ? inner->GetRect().height : 0);
   } else {
--- a/layout/reftests/forms/fieldset/reftest.list
+++ b/layout/reftests/forms/fieldset/reftest.list
@@ -1,8 +1,11 @@
 == dynamic-legend-scroll-1.html dynamic-legend-scroll-1-ref.html
 == fieldset-hidden-1.html fieldset-hidden-1-ref.html
 == fieldset-intrinsic-width-1.html fieldset-intrinsic-width-1-ref.html
 == fieldset-percentage-padding-1.html fieldset-percentage-padding-1-ref.html
 == fieldset-scroll-1.html fieldset-scroll-1-ref.html
 == fieldset-scrolled-1.html fieldset-scrolled-1-ref.html
 random-if(B2G) == fieldset-overflow-auto-1.html fieldset-overflow-auto-1-ref.html
 == positioned-container-1.html positioned-container-1-ref.html
+== relpos-legend-1.html relpos-legend-1-ref.html
+== relpos-legend-2.html relpos-legend-2-ref.html
+== sticky-legend-1.html sticky-legend-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/relpos-legend-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset>
+  <legend><div style="position:relative; top:20px">Legend</div></legend>
+</fieldset>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/relpos-legend-1.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset>
+  <legend style="position:relative; top:20px">Legend</legend>
+</fieldset>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/relpos-legend-2-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset>
+  <legend><span style="position:relative; top:20px">Legend</span></legend>
+</fieldset>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/relpos-legend-2.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset>
+  <legend style="display:inline; position:relative; top:20px">Legend</legend>
+</fieldset>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/sticky-legend-1-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset style="overflow:hidden; height:300px;">
+  <legend style="position:fixed; top:0"><div style="width:200px; height:50px; background:yellow;"></div></legend>
+</fieldset>
+<div style="height:5000px;"></div>
+<script>
+window.scrollTo(0,100);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/fieldset/sticky-legend-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<fieldset style="overflow:hidden; height:300px;">
+  <legend style="position:sticky; top:0;"><div style="width:200px; height:50px; background:yellow;"></div></legend>
+</fieldset>
+<div style="height:5000px;"></div>
+<script>
+window.scrollTo(0,100);
+</script>
+</body>
+</html>