From c6b693613e20c402f8d97664606a14a00ac2e86f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 30 Nov 2015 19:13:20 -0500 Subject: [PATCH] Bug 1228597 - Clean up code paths that (un)apply a pres shell resolution. r=tn,botond A clear separation is introduced between paths that deal with a root document resolution (at the process boundary in e10s setups) and paths that deal with a non-root document resolution (elsewhere in Layout code). This allows both code paths to run on all platforms. --- dom/base/nsContentUtils.cpp | 3 +- dom/events/Event.cpp | 2 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 54 ++++++++++++++++------ layout/base/nsIPresShell.h | 7 ++- layout/base/nsLayoutUtils.cpp | 7 +-- layout/base/nsPresShell.cpp | 9 ++-- layout/base/nsPresShell.h | 2 +- 7 files changed, 60 insertions(+), 24 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index a9e190f2ab7..cb03257586b 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7672,7 +7672,8 @@ nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint, nsPresContext* aPresContext) { return LayoutDeviceIntPoint::FromAppUnitsRounded( - (CSSPoint::ToAppUnits(aPoint) + aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution()), + (CSSPoint::ToAppUnits(aPoint) + + aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()), aPresContext->AppUnitsPerDevPixel()); } diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index cc98210544c..9d12b2fb460 100644 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -936,7 +936,7 @@ Event::GetScreenCoords(nsPresContext* aPresContext, LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom()); if (aPresContext->PresShell()) { - pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeScaleResolution()); + pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()); } pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(), diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 0aead3fbfb7..5ef6a4aed43 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -415,6 +415,28 @@ APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aConte return context->PresShell(); } +static nsIPresShell* +GetRootDocumentPresShell(nsIContent* aContent) +{ + nsIDocument* doc = aContent->GetComposedDoc(); + if (!doc) { + return nullptr; + } + nsIPresShell* shell = doc->GetShell(); + if (!shell) { + return nullptr; + } + nsPresContext* context = shell->GetPresContext(); + if (!context) { + return nullptr; + } + context = context->GetRootPresContext(); + if (!context) { + return nullptr; + } + return context->PresShell(); +} + CSSPoint APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput, const ScrollableLayerGuid& aGuid) @@ -423,7 +445,21 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput, if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) { return input; } - // Apply the callback-transform. + nsCOMPtr content = nsLayoutUtils::FindContentFor(aGuid.mScrollId); + if (!content) { + return input; + } + + // First, scale inversely by the root content document's pres shell + // resolution to cancel the scale-to-resolution transform that the + // compositor adds to the layer with the pres shell resolution. The points + // sent to Gecko by APZ don't have this transform unapplied (unlike other + // compositor-side transforms) because APZ doesn't know about it. + if (nsIPresShell* shell = GetRootDocumentPresShell(content)) { + input = input / shell->GetResolution(); + } + + // Now apply the callback-transform. // XXX: technically we need to walk all the way up the layer tree from the layer // represented by |aGuid.mScrollId| up to the root of the layer tree and apply // the input transforms at each level in turn. However, it is quite difficult @@ -434,19 +470,9 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput, // some things transformed improperly. In practice we should rarely hit scenarios // where any of this matters, so I'm skipping it for now and just doing the single // transform for the layer that the input hit. - nsCOMPtr content = nsLayoutUtils::FindContentFor(aGuid.mScrollId); - if (content) { - void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform); - CSSPoint delta = property ? (*static_cast(property)) : CSSPoint(0.0f, 0.0f); - // The delta is in root content document coordinate space while the - // aInput point is in root document coordinate space so convert the - // delta to root document space before adding it to the aInput point. - float resolution = 1.0f; - if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) { - resolution = shell->GetResolution(); - } - delta.x = delta.x * resolution; - delta.y = delta.y * resolution; + void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform); + if (property) { + CSSPoint delta = (*static_cast(property)); input += delta; } return input; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index a8565fd20ee..4bf20043b3f 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1416,7 +1416,12 @@ public: virtual nsresult SetResolution(float aResolution) = 0; float GetResolution() { return mResolution.valueOr(1.0); } virtual float GetCumulativeResolution() = 0; - virtual float GetCumulativeScaleResolution() = 0; + + /** + * Calculate the cumulative scale resolution from this document up to + * but not including the root document. + */ + virtual float GetCumulativeNonRootScaleResolution() = 0; /** * Was the current resolution set by the user or just default initialized? diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index ef17dc14f15..4398c900635 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2021,7 +2021,7 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget, nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x), presContext->DevPixelsToAppUnits(aPoint.y)); pt = pt - view->ViewToWidgetOffset(); - pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeScaleResolution()); + pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeNonRootScaleResolution()); return pt; } } @@ -2060,7 +2060,7 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget, nsIPresShell* shell = aFrame->PresContext()->PresShell(); // XXX Bug 1224748 - Update nsLayoutUtils functions to correctly handle nsPresShell resolution - widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeScaleResolution()); + widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeNonRootScaleResolution()); /* If we encountered a transform, we can't do simple arithmetic to figure * out how to convert back to aFrame's coordinates and must use the CTM. @@ -2808,7 +2808,8 @@ nsLayoutUtils::TranslateViewToWidget(nsPresContext* aPresContext, return LayoutDeviceIntPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); } - nsPoint pt = (aPt + viewOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution()); + nsPoint pt = (aPt + + viewOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeNonRootScaleResolution()); LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(pt.x), aPresContext->AppUnitsToDevPixels(pt.y)); return relativeToViewWidget + WidgetToWidgetOffset(viewWidget, aWidget); diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 4be651cfd6b..6bb8e81fa10 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5330,13 +5330,16 @@ float PresShell::GetCumulativeResolution() return resolution; } -float PresShell::GetCumulativeScaleResolution() +float PresShell::GetCumulativeNonRootScaleResolution() { float resolution = 1.0; nsIPresShell* currentShell = this; while (currentShell) { - resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f; - nsPresContext* parentCtx = currentShell->GetPresContext()->GetParentPresContext(); + nsPresContext* currentCtx = currentShell->GetPresContext(); + if (currentCtx != currentCtx->GetRootPresContext()) { + resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f; + } + nsPresContext* parentCtx = currentCtx->GetParentPresContext(); if (parentCtx) { currentShell = parentCtx->PresShell(); } else { diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index b2ad8ed8733..5479bd504b1 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -218,7 +218,7 @@ public: } virtual bool ScaleToResolution() const override; virtual float GetCumulativeResolution() override; - virtual float GetCumulativeScaleResolution() override; + virtual float GetCumulativeNonRootScaleResolution() override; //nsIViewObserver interface