Bug 811403 (Part 1) - Take scrollbars into account for viewport units if 'overflow: scroll' is set. r=dbaron

This commit is contained in:
Seth Fowler 2013-04-01 17:02:57 -07:00
parent 47f0c99c37
commit 81c3ba6eb9

View File

@ -38,6 +38,7 @@
#include "nsContentUtils.h"
#include "CSSCalc.h"
#include "nsPrintfCString.h"
#include "nsRenderingContext.h"
#include "mozilla/LookAndFeel.h"
@ -229,6 +230,51 @@ GetMetricsFor(nsPresContext* aPresContext,
return fm.forget();
}
static nsSize CalcViewportUnitsScale(nsPresContext* aPresContext)
{
// The caller is making use of viewport units, so notify the pres context
// that it will need to rebuild the rule tree if the size of the viewport
// changes.
aPresContext->SetUsesViewportUnits(true);
// The default (when we have 'overflow: auto' on the root element, or
// trivially for 'overflow: hidden' since we never have scrollbars in that
// case) is to define the scale of the viewport units without considering
// scrollbars.
nsSize viewportSize(aPresContext->GetVisibleArea().Size());
// Check for 'overflow: scroll' styles on the root scroll frame. If we find
// any, the standard requires us to take scrollbars into account.
nsIScrollableFrame* scrollFrame =
aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
if (scrollFrame) {
nsPresContext::ScrollbarStyles styles(scrollFrame->GetScrollbarStyles());
if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
// Gather scrollbar size information.
nsRefPtr<nsRenderingContext> context =
aPresContext->PresShell()->GetReferenceRenderingContext();
nsMargin sizes(scrollFrame->GetDesiredScrollbarSizes(aPresContext, context));
if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) {
// 'overflow-x: scroll' means we must consider the horizontal scrollbar,
// which affects the scale of viewport height units.
viewportSize.height -= sizes.TopBottom();
}
if (styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
// 'overflow-y: scroll' means we must consider the vertical scrollbar,
// which affects the scale of viewport width units.
viewportSize.width -= sizes.LeftRight();
}
}
}
return viewportSize;
}
static nscoord CalcLengthWith(const nsCSSValue& aValue,
nscoord aFontSize,
const nsStyleFont* aStyleFont,
@ -286,22 +332,18 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
// for an increased cost to dynamic changes to the viewport size
// when viewport units are in use.
case eCSSUnit_ViewportWidth: {
aPresContext->SetUsesViewportUnits(true);
return ScaleCoord(aValue, 0.01f * aPresContext->GetVisibleArea().width);
return ScaleCoord(aValue, 0.01f * CalcViewportUnitsScale(aPresContext).width);
}
case eCSSUnit_ViewportHeight: {
aPresContext->SetUsesViewportUnits(true);
return ScaleCoord(aValue, 0.01f * aPresContext->GetVisibleArea().height);
return ScaleCoord(aValue, 0.01f * CalcViewportUnitsScale(aPresContext).height);
}
case eCSSUnit_ViewportMin: {
aPresContext->SetUsesViewportUnits(true);
nsSize viewportSize = aPresContext->GetVisibleArea().Size();
return ScaleCoord(aValue, 0.01f * min(viewportSize.width, viewportSize.height));
nsSize vuScale(CalcViewportUnitsScale(aPresContext));
return ScaleCoord(aValue, 0.01f * min(vuScale.width, vuScale.height));
}
case eCSSUnit_ViewportMax: {
aPresContext->SetUsesViewportUnits(true);
nsSize viewportSize = aPresContext->GetVisibleArea().Size();
return ScaleCoord(aValue, 0.01f * max(viewportSize.width, viewportSize.height));
nsSize vuScale(CalcViewportUnitsScale(aPresContext));
return ScaleCoord(aValue, 0.01f * max(vuScale.width, vuScale.height));
}
// While we could deal with 'rem' units correctly by simply not
// caching any data that uses them in the rule tree, it's valuable