diff --git a/layout/base/UnitTransforms.h b/layout/base/UnitTransforms.h index cb8ca9d2b80..8f5c116e894 100644 --- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -49,6 +49,14 @@ template gfx::IntSizeTyped ViewAs(const nsIntSize& aSize) { return gfx::IntSizeTyped(aSize.width, aSize.height); } +template +gfx::IntPointTyped ViewAs(const nsIntPoint& aPoint) { + return gfx::IntPointTyped(aPoint.x, aPoint.y); +} +template +gfx::IntRectTyped ViewAs(const nsIntRect& aRect) { + return gfx::IntRectTyped(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 diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5f550a588d2..98f1e1e8f10 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -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( + (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(bounds.Size())); + nsIntRect widgetBounds; + widget->GetBounds(widgetBounds); + rootCompositionSize = LayerSize(ViewAs(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( - (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(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; } } } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index b090e7cb5f5..023242faac3 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -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; } } }