Bug 1280013 - Incorporate the APZ callback transforms when using the root composition bounds to clip the displayport base. r?botond,tnikkel
MozReview-Commit-ID: 8N1MUjEjvGC
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -395,49 +395,29 @@ APZCCallbackHelper::ApplyCallbackTransfo
if (nsIPresShell* shell = GetRootDocumentPresShell(content)) {
input = input / shell->GetResolution();
}
// This represents any resolution on the Root Content Document (RCD)
// that's not on the Root Document (RD). That is, on platforms where
// RCD == RD, it's 1, and on platforms where RCD != RD, it's the RCD
// resolution. 'input' has this resolution applied, but the scroll
- // deltas retrieved below do not, so we need to apply them to the
- // deltas before adding the deltas to 'input'. (Technically, deltas
+ // delta retrieved below do not, so we need to apply them to the
+ // delta before adding the delta to 'input'. (Technically, deltas
// from scroll frames outside the RCD would already have this
// resolution applied, but we don't have such scroll frames in
// practice.)
float nonRootResolution = 1.0f;
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
nonRootResolution = shell->GetCumulativeNonRootScaleResolution();
}
- // Now apply the callback-transform.
- // XXX: Walk up the frame tree from the frame of this content element
- // to the root of the frame tree, and apply any apzCallbackTransform
- // found on the way. This is only approximately correct, as it does
- // not take into account CSS transforms, nor differences in structure between
- // the frame tree (which determines the transforms we're applying)
- // and the layer tree (which determines the transforms we *want* to
- // apply).
- nsIFrame* frame = content->GetPrimaryFrame();
- nsCOMPtr<nsIContent> lastContent;
- while (frame) {
- if (content && (content != lastContent)) {
- void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
- if (property) {
- CSSPoint delta = (*static_cast<CSSPoint*>(property));
- delta = delta * nonRootResolution;
- input += delta;
- }
- }
- frame = frame->GetParent();
- lastContent = content;
- content = frame ? frame->GetContent() : nullptr;
- }
- return input;
+ // Now apply the callback-transform. This is only approximately correct,
+ // see the comment on GetCumulativeApzCallbackTransform for details.
+ CSSPoint transform = nsLayoutUtils::GetCumulativeApzCallbackTransform(content->GetPrimaryFrame());
+ return input + transform * nonRootResolution;
}
LayoutDeviceIntPoint
APZCCallbackHelper::ApplyCallbackTransform(const LayoutDeviceIntPoint& aPoint,
const ScrollableLayerGuid& aGuid,
const CSSToLayoutDeviceScale& aScale)
{
LayoutDevicePoint point = LayoutDevicePoint(aPoint.x, aPoint.y);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9326,8 +9326,31 @@ nsLayoutUtils::IsTransformed(nsIFrame* a
for (nsIFrame* f = aForFrame; f != aTopFrame; f = f->GetParent()) {
if (f->IsTransformed()) {
return true;
}
}
return false;
}
+/*static*/ CSSPoint
+nsLayoutUtils::GetCumulativeApzCallbackTransform(nsIFrame* aFrame)
+{
+ CSSPoint delta;
+ if (!aFrame) {
+ return delta;
+ }
+ nsIFrame* frame = aFrame;
+ nsCOMPtr<nsIContent> content = frame->GetContent();
+ nsCOMPtr<nsIContent> lastContent;
+ while (frame) {
+ if (content && (content != lastContent)) {
+ void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
+ if (property) {
+ delta += *static_cast<CSSPoint*>(property);
+ }
+ }
+ frame = GetCrossDocParentFrame(frame);
+ lastContent = content;
+ content = frame ? frame->GetContent() : nullptr;
+ }
+ return delta;
+}
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2831,16 +2831,26 @@ public:
/**
* Walks up the frame tree from |aForFrame| up to |aTopFrame|, or to the
* root of the frame tree if |aTopFrame| is nullptr, and returns true if
* a transformed frame is encountered.
*/
static bool IsTransformed(nsIFrame* aForFrame, nsIFrame* aTopFrame = nullptr);
+ /**
+ * Walk up from aFrame to the cross-doc root, accumulating all the APZ callback
+ * transforms on the content elements encountered along the way. Return the
+ * accumulated value.
+ * XXX: Note that this does not take into account CSS transforms, nor
+ * differences in structure between the frame tree and the layer tree (which
+ * is probably what we *want* to be computing).
+ */
+ static CSSPoint GetCumulativeApzCallbackTransform(nsIFrame* aFrame);
+
private:
static uint32_t sFontSizeInflationEmPerLine;
static uint32_t sFontSizeInflationMinTwips;
static uint32_t sFontSizeInflationLineThreshold;
static int32_t sFontSizeInflationMappingIntercept;
static uint32_t sFontSizeInflationMaxRatio;
static bool sFontSizeInflationForceEnabled;
static bool sFontSizeInflationDisabledInMasterProcess;
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -3529,17 +3529,30 @@ ScrollFrameHelper::DecideScrollableLayer
// If rootFrame is the RCD-RSF then CalculateCompositionSizeForFrame
// did not take the document's resolution into account, so we must.
if (rootPresContext->IsRootContentDocument() &&
rootFrame == rootPresShell->GetRootScrollFrame()) {
rootCompBounds = rootCompBounds.RemoveResolution(rootPresShell->GetResolution());
}
+ // We want to convert the root composition bounds from the coordinate
+ // space of |rootFrame| to the coordinate space of |mOuter|. We do
+ // that with the TransformRect call below. However, since we care
+ // about the root composition bounds relative to what the user is
+ // actually seeing, we also need to incorporate the APZ callback
+ // transforms into this. Most of the time those transforms are
+ // negligible, but in some cases (e.g. when a zoom is applied on
+ // an overflow:hidden document) it is not (see bug 1280013).
+ // XXX: Eventually we may want to create a modified version of
+ // TransformRect that includes the APZ callback transforms
+ // directly.
nsLayoutUtils::TransformRect(rootFrame, mOuter, rootCompBounds);
+ rootCompBounds += CSSPoint::ToAppUnits(
+ nsLayoutUtils::GetCumulativeApzCallbackTransform(mOuter));
displayportBase = displayportBase.Intersect(rootCompBounds);
}
}
}
displayportBase -= mScrollPort.TopLeft();
}