Bug 988882 - Special-case handling of root composition bounds calculation on Android when the toolbar is perma-visible. r=tn

This commit is contained in:
Botond Ballo 2014-04-02 01:35:25 -04:00
parent 97a3052587
commit 6ae1c0501f
3 changed files with 78 additions and 53 deletions

View File

@ -49,6 +49,14 @@ template <class TargetUnits>
gfx::IntSizeTyped<TargetUnits> ViewAs(const nsIntSize& aSize) {
return gfx::IntSizeTyped<TargetUnits>(aSize.width, aSize.height);
}
template <class TargetUnits>
gfx::IntPointTyped<TargetUnits> ViewAs(const nsIntPoint& aPoint) {
return gfx::IntPointTyped<TargetUnits>(aPoint.x, aPoint.y);
}
template <class TargetUnits>
gfx::IntRectTyped<TargetUnits> ViewAs(const nsIntRect& aRect) {
return gfx::IntRectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
}
// Convenience functions for casting typed entities to untyped entities.
// Using these functions does not require a justification, but once we convert

View File

@ -642,30 +642,37 @@ CalculateRootCompositionSize(FrameMetrics& aMetrics,
}
nsIPresShell* rootPresShell = nullptr;
if (rootPresContext) {
// See the comments in the code that calculates the root
// composition bounds in RecordFrameMetrics.
// TODO: Reuse that code here.
nsIPresShell* rootPresShell = rootPresContext->PresShell();
if (nsIFrame* rootFrame = rootPresShell->GetRootFrame()) {
if (nsView* view = rootFrame->GetView()) {
nsIWidget* widget = view->GetWidget();
#ifdef MOZ_WIDGET_ANDROID
// Android hack - temporary workaround for bug 983208 until we figure
// out what a proper fix is.
if (!widget) {
widget = rootFrame->GetNearestWidget();
}
#endif
LayoutDeviceToParentLayerScale parentResolution(
rootPresShell->GetCumulativeResolution().width
/ rootPresShell->GetResolution().width);
int32_t rootAUPerDevPixel = rootPresContext->AppUnitsPerDevPixel();
nsRect viewBounds = view->GetBounds();
LayerSize viewSize = ViewAs<LayerPixel>(
(LayoutDeviceRect::FromAppUnits(viewBounds, rootAUPerDevPixel)
* parentResolution).Size(), PixelCastJustification::ParentLayerToLayerForRootComposition);
nsIWidget* widget =
#ifdef MOZ_WIDGET_ANDROID
rootFrame->GetNearestWidget();
#else
view->GetWidget();
#endif
if (widget) {
nsIntRect bounds;
widget->GetBounds(bounds);
rootCompositionSize = LayerSize(ViewAs<LayerPixel>(bounds.Size()));
nsIntRect widgetBounds;
widget->GetBounds(widgetBounds);
rootCompositionSize = LayerSize(ViewAs<LayerPixel>(widgetBounds.Size()));
#ifdef MOZ_WIDGET_ANDROID
if (viewSize.height < rootCompositionSize.height) {
rootCompositionSize.height = viewSize.height;
}
#endif
} else {
LayoutDeviceToParentLayerScale parentResolution(
rootPresShell->GetCumulativeResolution().width
/ rootPresShell->GetResolution().width);
int32_t rootAUPerDevPixel = rootPresContext->AppUnitsPerDevPixel();
nsRect viewBounds = view->GetBounds();
rootCompositionSize = ViewAs<LayerPixel>(
(LayoutDeviceRect::FromAppUnits(viewBounds, rootAUPerDevPixel)
* parentResolution).Size(), PixelCastJustification::ParentLayerToLayerForRootComposition);
rootCompositionSize = viewSize;
}
}
}
@ -793,7 +800,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
nsRect compositionBounds(frameForCompositionBoundsCalculation->GetOffsetToCrossDoc(aReferenceFrame),
frameForCompositionBoundsCalculation->GetSize());
metrics.mCompositionBounds = RoundedToInt(LayoutDeviceRect::FromAppUnits(compositionBounds, auPerDevPixel)
* metrics.GetParentResolution());
* metrics.GetParentResolution());
// For the root scroll frame of the root content document, the above calculation
// will yield the size of the viewport frame as the composition bounds, which
@ -808,23 +815,35 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
if (isRootContentDocRootScrollFrame) {
if (nsIFrame* rootFrame = presShell->GetRootFrame()) {
if (nsView* view = rootFrame->GetView()) {
nsIWidget* widget = view->GetWidget();
nsRect viewBoundsAppUnits = view->GetBounds() + rootFrame->GetOffsetToCrossDoc(aReferenceFrame);
ParentLayerIntRect viewBounds = RoundedToInt(LayoutDeviceRect::FromAppUnits(viewBoundsAppUnits, auPerDevPixel)
* metrics.GetParentResolution());
// On Android, we need to do things a bit differently to get things
// right (see bug 983208, bug 988882). We use the bounds of the nearest
// widget, but clamp the height to the view bounds height. This clamping
// is done to get correct results for a page where the page is sized to
// the screen and thus the dynamic toolbar never disappears. In such a
// case, we want the composition bounds to exclude the toolbar height,
// but the widget bounds includes it. We don't currently have a good way
// of knowing about the toolbar height, but clamping to the view bounds
// height gives the correct answer in the cases we care about.
nsIWidget* widget =
#ifdef MOZ_WIDGET_ANDROID
// Android hack - temporary workaround for bug 983208 until we figure
// out what a proper fix is.
if (!widget) {
widget = rootFrame->GetNearestWidget();
}
rootFrame->GetNearestWidget();
#else
view->GetWidget();
#endif
if (widget) {
nsIntRect bounds;
widget->GetBounds(bounds);
metrics.mCompositionBounds = ParentLayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
bounds.x, bounds.y, bounds.width, bounds.height));
nsIntRect widgetBounds;
widget->GetBounds(widgetBounds);
metrics.mCompositionBounds = ViewAs<ParentLayerPixel>(widgetBounds);
#ifdef MOZ_WIDGET_ANDROID
if (viewBounds.height < metrics.mCompositionBounds.height) {
metrics.mCompositionBounds.height = viewBounds.height;
}
#endif
} else {
nsRect viewBounds = view->GetBounds() + rootFrame->GetOffsetToCrossDoc(aReferenceFrame);
metrics.mCompositionBounds = RoundedToInt(LayoutDeviceRect::FromAppUnits(viewBounds, auPerDevPixel)
* metrics.GetParentResolution());
metrics.mCompositionBounds = viewBounds;
}
}
}

View File

@ -6170,36 +6170,34 @@ nsLayoutUtils::CalculateCompositionSizeForFrame(nsIFrame* aFrame)
nsPresContext* presContext = aFrame->PresContext();
nsIPresShell* presShell = presContext->PresShell();
// For the root scroll frame of the root content document, the above calculation
// will yield the size of the viewport frame as the composition bounds, which
// doesn't actually correspond to what is visible when
// nsIDOMWindowUtils::setCSSViewport has been called to modify the visible area of
// the prescontext that the viewport frame is reflowed into. In that case if our
// document has a widget then the widget's bounds will correspond to what is
// visible. If we don't have a widget the root view's bounds correspond to what
// would be visible because they don't get modified by setCSSViewport.
// See the comments in the code that calculates the root
// composition bounds in RecordFrameMetrics.
// TODO: Reuse that code here.
bool isRootContentDocRootScrollFrame = presContext->IsRootContentDocument()
&& aFrame == presShell->GetRootScrollFrame();
if (isRootContentDocRootScrollFrame) {
if (nsIFrame* rootFrame = presShell->GetRootFrame()) {
if (nsView* view = rootFrame->GetView()) {
nsIWidget* widget = view->GetWidget();
nsSize viewSize = view->GetBounds().Size();
nsIWidget* widget =
#ifdef MOZ_WIDGET_ANDROID
// Android hack - temporary workaround for bug 983208 until we figure
// out what a proper fix is.
if (!widget) {
widget = rootFrame->GetNearestWidget();
}
rootFrame->GetNearestWidget();
#else
view->GetWidget();
#endif
if (widget) {
nsIntRect bounds;
widget->GetBounds(bounds);
nsIntRect widgetBounds;
widget->GetBounds(widgetBounds);
int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel();
size = nsSize(bounds.width * auPerDevPixel,
bounds.height * auPerDevPixel);
size = nsSize(widgetBounds.width * auPerDevPixel,
widgetBounds.height * auPerDevPixel);
#ifdef MOZ_WIDGET_ANDROID
if (viewSize.height < size.height) {
size.height = viewSize.height;
}
#endif
} else {
nsRect viewBounds = view->GetBounds();
size = nsSize(viewBounds.width, viewBounds.height);
size = viewSize;
}
}
}