diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 1432abdcf34..6df44ae3619 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" #include "nsStyleConsts.h" +#include "nsCSSAnonBoxes.h" #include "nsFrame.h" #include "nsIContent.h" #include "nsHTMLAtoms.h" @@ -1359,20 +1360,22 @@ GetVerticalMarginBorderPadding(const nsHTMLReflowState* aReflowState) /* Get the height based on the viewport of the containing block specified * in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT * This will walk up the chain of containing blocks looking for a computed height - * until it finds the canvas frame, or it encounters a frame that is not a block - * or and area frame. This handles compatibility with IE (see bug 85016) + * until it finds the canvas frame, or it encounters a frame that is not a block, + * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693) * - * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the first parent - * block or area frame. When FALSE, we look all the way up the frame tree, through nested - * blocks and area frames, and always find a real height. This is needed for percentage-height - * images in unconstrained blocks, like DIVs (see bugzilla bug 85016) + * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the second parent + * block, area, or scroll frame. When FALSE, we look all the way up the frame tree, through nested + * block, area, and scroll frames, and always find a real height. This is needed for percentage-height + * images in unconstrained blocks, like DIVs (see bugzilla bug 85016). + * + * When we encounter scrolledContent area frames, we skip over them, since they are guaranteed to not be useful for computing the containing block. */ nscoord CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, PRBool aRestrictToFirstLevel) { - nsHTMLReflowState* firstBlockRS = nsnull; // a candidate for body frame - nsHTMLReflowState* firstAreaRS = nsnull; // a candidate for html frame + nsHTMLReflowState* firstAncestorRS = nsnull; // a candidate for html frame + nsHTMLReflowState* secondAncestorRS = nsnull; // a candidate for body frame // initialize the default to NS_AUTOHEIGHT as this is the containings block // computed height when this function is called. It is possible that we @@ -1385,25 +1388,25 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, rs->frame->GetFrameType(getter_AddRefs(frameType)); // if the ancestor is auto height then skip it and continue up if it // is the first block/area frame and possibly the body/html - if (nsLayoutAtoms::blockFrame == frameType.get()) { - if (aRestrictToFirstLevel && firstBlockRS) { + if (nsLayoutAtoms::blockFrame == frameType || + nsLayoutAtoms::areaFrame == frameType || + nsLayoutAtoms::scrollFrame == frameType) { + if (nsLayoutAtoms::areaFrame == frameType) { + nsCOMPtr pseudo = rs->frame->GetStyleContext()->GetPseudoType(); + if (pseudo == nsCSSAnonBoxes::scrolledContent) { + continue; + } + } + if (aRestrictToFirstLevel && firstAncestorRS && secondAncestorRS) { break; } - firstBlockRS = (nsHTMLReflowState*)rs; + secondAncestorRS = firstAncestorRS; + firstAncestorRS = (nsHTMLReflowState*)rs; if (NS_AUTOHEIGHT == rs->mComputedHeight) { continue; } } - else if (nsLayoutAtoms::areaFrame == frameType.get()) { - if (aRestrictToFirstLevel && firstAreaRS) { - break; - } - firstAreaRS = (nsHTMLReflowState*)rs; - if (NS_AUTOHEIGHT == rs->mComputedHeight) { - continue; - } - } - else if (nsLayoutAtoms::canvasFrame == frameType.get()) { + else if (nsLayoutAtoms::canvasFrame == frameType) { // Use scroll frames' computed height if we have one, this will // allow us to get viewport height for native scrollbars. nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState; @@ -1413,7 +1416,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, rs = scrollState; } } - else if (nsLayoutAtoms::pageContentFrame == frameType.get()) { + else if (nsLayoutAtoms::pageContentFrame == frameType) { nsIFrame* prevInFlow; rs->frame->GetPrevInFlow(&prevInFlow); // only use the page content frame for a height basis if it is the first in flow @@ -1426,35 +1429,35 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, // if the ancestor is the page content frame then the percent base is // the avail height, otherwise it is the computed height - result = (nsLayoutAtoms::pageContentFrame == frameType.get()) + result = (nsLayoutAtoms::pageContentFrame == frameType) ? rs->availableHeight : rs->mComputedHeight; // if unconstrained - don't sutract borders - would result in huge height if (NS_AUTOHEIGHT == result) return result; // if we got to the canvas or page content frame, then subtract out // margin/border/padding for the BODY and HTML elements - if ((nsLayoutAtoms::canvasFrame == frameType.get()) || - (nsLayoutAtoms::pageContentFrame == frameType.get())) { + if ((nsLayoutAtoms::canvasFrame == frameType) || + (nsLayoutAtoms::pageContentFrame == frameType)) { - result -= GetVerticalMarginBorderPadding(firstBlockRS); - result -= GetVerticalMarginBorderPadding(firstAreaRS); + result -= GetVerticalMarginBorderPadding(firstAncestorRS); + result -= GetVerticalMarginBorderPadding(secondAncestorRS); #ifdef DEBUG - // make sure the Area is the HTML and the Block is the BODY - if (firstBlockRS) { - nsIContent* frameContent = firstBlockRS->frame->GetContent(); + // make sure the first ancestor is the HTML and the second is the BODY + if (firstAncestorRS) { + nsIContent* frameContent = firstAncestorRS->frame->GetContent(); if (frameContent) { nsCOMPtr contentTag; frameContent->GetTag(getter_AddRefs(contentTag)); - NS_ASSERTION(contentTag.get() == nsHTMLAtoms::body, "block is not BODY"); + NS_ASSERTION(contentTag == nsHTMLAtoms::html, "First ancestor is not HTML"); } } - if (firstAreaRS) { - nsIContent* frameContent = firstAreaRS->frame->GetContent(); + if (secondAncestorRS) { + nsIContent* frameContent = secondAncestorRS->frame->GetContent(); if (frameContent) { nsCOMPtr contentTag; frameContent->GetTag(getter_AddRefs(contentTag)); - NS_ASSERTION(contentTag.get() == nsHTMLAtoms::html, "Area frame is not HTML element"); + NS_ASSERTION(contentTag == nsHTMLAtoms::body, "Second ancestor is not BODY"); } } #endif @@ -1462,12 +1465,12 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, } // if we got to the html frame, then subtract out // margin/border/padding for the BODY element - else if (nsLayoutAtoms::areaFrame == frameType.get()) { + else if (nsLayoutAtoms::areaFrame == frameType) { // make sure it is the body nsCOMPtr fType; rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType)); - if (nsLayoutAtoms::canvasFrame == fType.get()) { - result -= GetVerticalMarginBorderPadding(firstBlockRS); + if (nsLayoutAtoms::canvasFrame == fType) { + result -= GetVerticalMarginBorderPadding(secondAncestorRS); } } break; diff --git a/layout/html/base/src/nsHTMLReflowState.cpp b/layout/html/base/src/nsHTMLReflowState.cpp index 1432abdcf34..6df44ae3619 100644 --- a/layout/html/base/src/nsHTMLReflowState.cpp +++ b/layout/html/base/src/nsHTMLReflowState.cpp @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" #include "nsStyleConsts.h" +#include "nsCSSAnonBoxes.h" #include "nsFrame.h" #include "nsIContent.h" #include "nsHTMLAtoms.h" @@ -1359,20 +1360,22 @@ GetVerticalMarginBorderPadding(const nsHTMLReflowState* aReflowState) /* Get the height based on the viewport of the containing block specified * in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT * This will walk up the chain of containing blocks looking for a computed height - * until it finds the canvas frame, or it encounters a frame that is not a block - * or and area frame. This handles compatibility with IE (see bug 85016) + * until it finds the canvas frame, or it encounters a frame that is not a block, + * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693) * - * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the first parent - * block or area frame. When FALSE, we look all the way up the frame tree, through nested - * blocks and area frames, and always find a real height. This is needed for percentage-height - * images in unconstrained blocks, like DIVs (see bugzilla bug 85016) + * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the second parent + * block, area, or scroll frame. When FALSE, we look all the way up the frame tree, through nested + * block, area, and scroll frames, and always find a real height. This is needed for percentage-height + * images in unconstrained blocks, like DIVs (see bugzilla bug 85016). + * + * When we encounter scrolledContent area frames, we skip over them, since they are guaranteed to not be useful for computing the containing block. */ nscoord CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, PRBool aRestrictToFirstLevel) { - nsHTMLReflowState* firstBlockRS = nsnull; // a candidate for body frame - nsHTMLReflowState* firstAreaRS = nsnull; // a candidate for html frame + nsHTMLReflowState* firstAncestorRS = nsnull; // a candidate for html frame + nsHTMLReflowState* secondAncestorRS = nsnull; // a candidate for body frame // initialize the default to NS_AUTOHEIGHT as this is the containings block // computed height when this function is called. It is possible that we @@ -1385,25 +1388,25 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, rs->frame->GetFrameType(getter_AddRefs(frameType)); // if the ancestor is auto height then skip it and continue up if it // is the first block/area frame and possibly the body/html - if (nsLayoutAtoms::blockFrame == frameType.get()) { - if (aRestrictToFirstLevel && firstBlockRS) { + if (nsLayoutAtoms::blockFrame == frameType || + nsLayoutAtoms::areaFrame == frameType || + nsLayoutAtoms::scrollFrame == frameType) { + if (nsLayoutAtoms::areaFrame == frameType) { + nsCOMPtr pseudo = rs->frame->GetStyleContext()->GetPseudoType(); + if (pseudo == nsCSSAnonBoxes::scrolledContent) { + continue; + } + } + if (aRestrictToFirstLevel && firstAncestorRS && secondAncestorRS) { break; } - firstBlockRS = (nsHTMLReflowState*)rs; + secondAncestorRS = firstAncestorRS; + firstAncestorRS = (nsHTMLReflowState*)rs; if (NS_AUTOHEIGHT == rs->mComputedHeight) { continue; } } - else if (nsLayoutAtoms::areaFrame == frameType.get()) { - if (aRestrictToFirstLevel && firstAreaRS) { - break; - } - firstAreaRS = (nsHTMLReflowState*)rs; - if (NS_AUTOHEIGHT == rs->mComputedHeight) { - continue; - } - } - else if (nsLayoutAtoms::canvasFrame == frameType.get()) { + else if (nsLayoutAtoms::canvasFrame == frameType) { // Use scroll frames' computed height if we have one, this will // allow us to get viewport height for native scrollbars. nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState; @@ -1413,7 +1416,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, rs = scrollState; } } - else if (nsLayoutAtoms::pageContentFrame == frameType.get()) { + else if (nsLayoutAtoms::pageContentFrame == frameType) { nsIFrame* prevInFlow; rs->frame->GetPrevInFlow(&prevInFlow); // only use the page content frame for a height basis if it is the first in flow @@ -1426,35 +1429,35 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, // if the ancestor is the page content frame then the percent base is // the avail height, otherwise it is the computed height - result = (nsLayoutAtoms::pageContentFrame == frameType.get()) + result = (nsLayoutAtoms::pageContentFrame == frameType) ? rs->availableHeight : rs->mComputedHeight; // if unconstrained - don't sutract borders - would result in huge height if (NS_AUTOHEIGHT == result) return result; // if we got to the canvas or page content frame, then subtract out // margin/border/padding for the BODY and HTML elements - if ((nsLayoutAtoms::canvasFrame == frameType.get()) || - (nsLayoutAtoms::pageContentFrame == frameType.get())) { + if ((nsLayoutAtoms::canvasFrame == frameType) || + (nsLayoutAtoms::pageContentFrame == frameType)) { - result -= GetVerticalMarginBorderPadding(firstBlockRS); - result -= GetVerticalMarginBorderPadding(firstAreaRS); + result -= GetVerticalMarginBorderPadding(firstAncestorRS); + result -= GetVerticalMarginBorderPadding(secondAncestorRS); #ifdef DEBUG - // make sure the Area is the HTML and the Block is the BODY - if (firstBlockRS) { - nsIContent* frameContent = firstBlockRS->frame->GetContent(); + // make sure the first ancestor is the HTML and the second is the BODY + if (firstAncestorRS) { + nsIContent* frameContent = firstAncestorRS->frame->GetContent(); if (frameContent) { nsCOMPtr contentTag; frameContent->GetTag(getter_AddRefs(contentTag)); - NS_ASSERTION(contentTag.get() == nsHTMLAtoms::body, "block is not BODY"); + NS_ASSERTION(contentTag == nsHTMLAtoms::html, "First ancestor is not HTML"); } } - if (firstAreaRS) { - nsIContent* frameContent = firstAreaRS->frame->GetContent(); + if (secondAncestorRS) { + nsIContent* frameContent = secondAncestorRS->frame->GetContent(); if (frameContent) { nsCOMPtr contentTag; frameContent->GetTag(getter_AddRefs(contentTag)); - NS_ASSERTION(contentTag.get() == nsHTMLAtoms::html, "Area frame is not HTML element"); + NS_ASSERTION(contentTag == nsHTMLAtoms::body, "Second ancestor is not BODY"); } } #endif @@ -1462,12 +1465,12 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, } // if we got to the html frame, then subtract out // margin/border/padding for the BODY element - else if (nsLayoutAtoms::areaFrame == frameType.get()) { + else if (nsLayoutAtoms::areaFrame == frameType) { // make sure it is the body nsCOMPtr fType; rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType)); - if (nsLayoutAtoms::canvasFrame == fType.get()) { - result -= GetVerticalMarginBorderPadding(firstBlockRS); + if (nsLayoutAtoms::canvasFrame == fType) { + result -= GetVerticalMarginBorderPadding(secondAncestorRS); } } break;