Bug 802457. Ensure that positioned children of intrinsic-height viewports are reflowed with the correct container height. r=mats
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 23 Oct 2012 14:48:12 +1300
changeset 111226 f18a8893e7ff0fd50bba83427b8ae0eb52ac369a
parent 111225 20279718e3c7a6f9f48aa6d4c86e4bf3c7e29af3
child 111227 6e108817d0c564adc2ab27ba379f8f85e6e6afde
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersmats
bugs802457
milestone19.0a1
Bug 802457. Ensure that positioned children of intrinsic-height viewports are reflowed with the correct container height. r=mats
layout/base/tests/chrome/Makefile.in
layout/base/tests/chrome/dialog_with_positioning_window.xul
layout/base/tests/chrome/test_dialog_with_positioning.html
layout/generic/nsViewportFrame.cpp
--- a/layout/base/tests/chrome/Makefile.in
+++ b/layout/base/tests/chrome/Makefile.in
@@ -40,17 +40,19 @@ MOCHITEST_CHROME_FILES = \
 	     printpreview_bug396024_helper.xul \
 	test_printpreview_bug482976.xul \
 	     printpreview_bug482976_helper.xul \
 	test_scrolling_repaints.html \
 	test_transformed_scrolling_repaints.html \
 	test_transformed_scrolling_repaints_2.html \
 	test_transformed_scrolling_repaints_3.html \
 	transformed_scrolling_repaints_3_window.html \
-	test_fixed_bg_scrolling_repaints.html \
+	     test_fixed_bg_scrolling_repaints.html \
+	test_dialog_with_positioning.html \
+	     dialog_with_positioning_window.xul \
 	blue-32x32.png \
 	$(NULL)
 
 ifdef MOZ_DEBUG
 # Disabled on Mac because of Bug 748219
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 MOCHITEST_CHROME_FILES += \
 	test_leaf_layers_partition_browser_window.xul \
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/chrome/dialog_with_positioning_window.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="setTimeout(runTest, 0)">
+  <vbox>
+    <text value="powered by example.com" style="padding: 16px;"/>
+  </vbox>
+  <hbox id="t" style="position: fixed; right: 16px; bottom: 16px;">
+    <button label="OK"/>
+  </hbox>
+<script><![CDATA[
+var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
+var SpecialPowers = window.opener.wrappedJSObject.SpecialPowers;
+var is = window.opener.wrappedJSObject.is;
+var ok = window.opener.wrappedJSObject.ok;
+
+// We run this off a setTimeout from onload, because the XUL window
+// only does its intrinsic-height layout after the load event has
+// finished
+function runTest() {
+  var t = document.getElementById("t");
+  var tBottom = t.getBoundingClientRect().bottom;
+  is(tBottom, document.documentElement.getBoundingClientRect().bottom - 16,
+     "check fixed-pos element t bottom positioned correctly");
+  ok(tBottom < 200, "fixed-pos element t bottom must be sane, less than 200 (got " + tBottom + ")");
+  window.close();
+  SimpleTest.finish();
+}
+]]></script>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/chrome/test_dialog_with_positioning.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test positioning of fixed-pos/abs-pos elements in a XUL dialog</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var root = getRootDirectory(window.location.href);
+window.openDialog(root + "dialog_with_positioning_window.xul", "dialog_with_positioning",
+                  "dialog,chrome");
+</script>
+</pre>
+</body>
+</html>
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -227,25 +227,36 @@ ViewportFrame::Reflow(nsPresContext*    
                           ? aReflowState.ComputedHeight()
                           : kidHeight;
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (mFrames.NotEmpty()) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
   }
 
-  // Make a copy of the reflow state and change the computed width and height
-  // to reflect the available space for the fixed items
-  nsHTMLReflowState reflowState(aReflowState);
+  if (IsAbsoluteContainer()) {
+    // Make a copy of the reflow state and change the computed width and height
+    // to reflect the available space for the fixed items
+    nsHTMLReflowState reflowState(aReflowState);
+
+    if (reflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
+      // We have an intrinsic-height document with abs-pos/fixed-pos children.
+      // Set the available height and mComputedHeight to our chosen height.
+      reflowState.availableHeight = aDesiredSize.height;
+      // Not having border/padding simplifies things
+      NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0,0,0,0),
+                   "Viewports can't have border/padding");
+      reflowState.SetComputedHeight(aDesiredSize.height);
+    }
+
 #ifdef DEBUG
-  nsPoint offset =
+    nsPoint offset =
 #endif
-    AdjustReflowStateForScrollbars(&reflowState);
+      AdjustReflowStateForScrollbars(&reflowState);
 
-  if (IsAbsoluteContainer()) {
     NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() ||
                  (offset.x == 0 && offset.y == 0),
                  "We don't handle correct positioning of fixed frames with "
                  "scrollbars in odd positions");
 
     // If a scroll position clamping scroll-port size has been set, layout
     // fixed position elements to this size instead of the computed size.
     nscoord width = reflowState.ComputedWidth();