Back out 7 changesets (bug 1274962) for timeouts in browser_tableWidget_mouse_interaction.js

CLOSED TREE

Backed out changeset c5c9bc65a408 (bug 1274962)
Backed out changeset 15b5f8019521 (bug 1274962)
Backed out changeset 9ac50a46557b (bug 1274962)
Backed out changeset 9cda37e5a581 (bug 1274962)
Backed out changeset bb0230c4bb6d (bug 1274962)
Backed out changeset 56ededfbdee6 (bug 1274962)
Backed out changeset e081fc6f3f90 (bug 1274962)
This commit is contained in:
Phil Ringnalda 2016-06-02 20:37:31 -07:00
parent 4ba56e35cf
commit f00b6395cb
8 changed files with 237 additions and 141 deletions

View File

@ -5625,10 +5625,11 @@ nsDisplayTransform::GetResultingTransformMatrix(const FrameTransformProperties&
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride)
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor)
{
return GetResultingTransformMatrixInternal(aProperties, aOrigin, aAppUnitsPerPixel,
aFlags, aBoundsOverride);
aFlags, aBoundsOverride, aOutAncestor);
}
Matrix4x4
@ -5636,14 +5637,15 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride)
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor)
{
FrameTransformProperties props(aFrame,
aAppUnitsPerPixel,
aBoundsOverride);
return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
aFlags, aBoundsOverride);
aFlags, aBoundsOverride, aOutAncestor);
}
Matrix4x4
@ -5651,10 +5653,17 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride)
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor)
{
const nsIFrame *frame = aProperties.mFrame;
NS_ASSERTION(frame || !(aFlags & INCLUDE_PERSPECTIVE), "Must have a frame to compute perspective!");
MOZ_ASSERT((aFlags & (OFFSET_BY_ORIGIN|BASIS_AT_ORIGIN)) != (OFFSET_BY_ORIGIN|BASIS_AT_ORIGIN),
"Can't specify offset by origin as well as basis at origin!");
if (aOutAncestor) {
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(frame);
}
// Get the underlying transform matrix:
@ -5696,6 +5705,16 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
result = Matrix4x4::From2D(svgTransform);
}
/* Account for the transform-origin property by translating the
* coordinate space to the new origin.
*/
Point3D newOrigin =
Point3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
0.0f);
Point3D roundedOrigin(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x),
hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y),
0);
Matrix4x4 perspectiveMatrix;
bool hasPerspective = aFlags & INCLUDE_PERSPECTIVE;
@ -5708,7 +5727,17 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
// This is a simplification of the following |else| block, the
// simplification being possible because we don't need to apply
// mToTransformOrigin between two transforms.
result.ChangeBasis(aProperties.mToTransformOrigin);
if ((aFlags & OFFSET_BY_ORIGIN) &&
!hasPerspective) {
// We can fold the final translation by roundedOrigin into the first matrix
// basis change translation. This is more stable against variation due to
// insufficient floating point precision than reversing the translation
// afterwards.
result.PreTranslate(-aProperties.mToTransformOrigin);
result.PostTranslate(roundedOrigin + aProperties.mToTransformOrigin);
} else {
result.ChangeBasis(aProperties.mToTransformOrigin);
}
} else {
Point3D refBoxOffset(NSAppUnitsToFloatPixels(refBox.X(), aAppUnitsPerPixel),
NSAppUnitsToFloatPixels(refBox.Y(), aAppUnitsPerPixel),
@ -5732,11 +5761,25 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
// Similar to the code in the |if| block above, but since we've accounted
// for mToTransformOrigin so we don't include that. We also need to reapply
// refBoxOffset.
result.ChangeBasis(refBoxOffset);
if ((aFlags & OFFSET_BY_ORIGIN) &&
!hasPerspective) {
result.PreTranslate(-refBoxOffset);
result.PostTranslate(roundedOrigin + refBoxOffset);
} else {
result.ChangeBasis(refBoxOffset);
}
}
if (hasPerspective) {
result = result * perspectiveMatrix;
if (aFlags & OFFSET_BY_ORIGIN) {
result.PostTranslate(roundedOrigin);
}
}
if (aFlags & BASIS_AT_ORIGIN) {
result.ChangeBasis(roundedOrigin);
}
if ((aFlags & INCLUDE_PRESERVE3D_ANCESTORS) &&
@ -5750,27 +5793,24 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
aAppUnitsPerPixel,
nullptr);
uint32_t flags = aFlags & (INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE);
// If this frame isn't transformed (but we exist for backface-visibility),
// then we're not a reference frame so no offset to origin will be added.
// Otherwise we need to manually translate into our parent's coordinate
// space.
if (frame->IsTransformed()) {
nsLayoutUtils::PostTranslate(result, frame->GetPosition(), aAppUnitsPerPixel, !hasSVGTransforms);
// then we're not a reference frame so no offset to origin will be added. Our
// parent transform however *is* the reference frame, so we pass
// OFFSET_BY_ORIGIN to convert into the correct coordinate space.
uint32_t flags = aFlags & (INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE);
if (!frame->IsTransformed()) {
flags |= OFFSET_BY_ORIGIN;
} else {
flags |= BASIS_AT_ORIGIN;
}
Matrix4x4 parent =
GetResultingTransformMatrixInternal(props,
nsPoint(0, 0),
aOrigin - frame->GetPosition(),
aAppUnitsPerPixel, flags,
nullptr);
nullptr, aOutAncestor);
result = result * parent;
}
if (aFlags & OFFSET_BY_ORIGIN) {
nsLayoutUtils::PostTranslate(result, aOrigin, aAppUnitsPerPixel, !hasSVGTransforms);
}
return result;
}
@ -5917,10 +5957,11 @@ nsDisplayTransform::GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBu
establisher && establisher->Combines3DTransformWithAncestors();
establisher = nsLayoutUtils::GetCrossDocParentFrame(establisher)) {
}
establisher = nsLayoutUtils::GetCrossDocParentFrame(establisher);
const nsIFrame* establisherReference =
aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetCrossDocParentFrame(establisher));
aBuilder->FindReferenceFrameFor(establisher);
nsPoint offset = establisher->GetOffsetToCrossDoc(establisherReference);
nsPoint offset = mFrame->GetOffsetToCrossDoc(establisherReference);
float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
uint32_t flags = INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN;
mTransformPreserves3D =
@ -6346,31 +6387,41 @@ nsDisplayTransform::TryMerge(nsDisplayItem *aItem)
*/
nsRect nsDisplayTransform::TransformRect(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsRect* aBoundsOverride)
const nsPoint &aOrigin,
const nsRect* aBoundsOverride,
bool aPreserves3D)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
uint32_t flags = INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN|INCLUDE_PRESERVE3D_ANCESTORS;
uint32_t flags = INCLUDE_PERSPECTIVE|BASIS_AT_ORIGIN;
if (aPreserves3D) {
flags |= INCLUDE_PRESERVE3D_ANCESTORS;
}
return nsLayoutUtils::MatrixTransformRect
(aUntransformedBounds,
GetResultingTransformMatrix(aFrame, nsPoint(0, 0), factor, flags, aBoundsOverride),
GetResultingTransformMatrix(aFrame, aOrigin, factor, flags, aBoundsOverride),
factor);
}
bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
nsRect *aOutRect)
const nsPoint &aOrigin,
nsRect *aOutRect,
bool aPreserves3D)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
uint32_t flags = INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN|INCLUDE_PRESERVE3D_ANCESTORS;
uint32_t flags = INCLUDE_PERSPECTIVE|BASIS_AT_ORIGIN;
if (aPreserves3D) {
flags |= INCLUDE_PRESERVE3D_ANCESTORS;
}
Matrix4x4 transform = GetResultingTransformMatrix(aFrame, nsPoint(0, 0), factor, flags);
Matrix4x4 transform = GetResultingTransformMatrix(aFrame, aOrigin, factor, flags);
if (transform.IsSingular()) {
return false;
}

View File

@ -1123,7 +1123,15 @@ public:
};
const nsRect GetPreserves3DDirtyRect(const nsIFrame *aFrame) const {
return mPreserves3DCtx.mDirtyRect;
nsRect dirty = mPreserves3DCtx.mDirtyRect;
// Translate the dirty rect to make it positioned relative to the
// origin of aFrame.
const nsIFrame *rootPreserves3D = aFrame;
while (rootPreserves3D && rootPreserves3D->Combines3DTransformWithAncestors()) {
dirty.MoveBy(-rootPreserves3D->GetPosition());
rootPreserves3D = rootPreserves3D->GetParent();
}
return dirty;
}
void SetPreserves3DDirtyRect(const nsRect &aDirtyRect) {
mPreserves3DCtx.mDirtyRect = aDirtyRect;
@ -3390,11 +3398,6 @@ public:
{
mParticipatesInPreserve3D = aParticipatesInPreserve3D;
}
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) override
{
return mParticipatesInPreserve3D;
}
private:
float mOpacity;
bool mForEventsOnly;
@ -4010,7 +4013,9 @@ public:
*/
static nsRect TransformRect(const nsRect &aUntransformedBounds,
const nsIFrame* aFrame,
const nsRect* aBoundsOverride = nullptr);
const nsPoint &aOrigin,
const nsRect* aBoundsOverride = nullptr,
bool aPreserves3D = true);
/* UntransformRect is like TransformRect, except that it inverts the
* transform.
@ -4018,7 +4023,9 @@ public:
static bool UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
nsRect *aOutRect);
const nsPoint &aOrigin,
nsRect *aOutRect,
bool aPreserves3D = true);
bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
nsRect* aOutRect);
@ -4071,6 +4078,9 @@ public:
* specify a value.
* @param aFlags OFFSET_BY_ORIGIN The resulting matrix will be translated
* by aOrigin. This translation is applied *before* the CSS transform.
* @param aFlags BASIS_AT_ORIGIN The resulting matrix will have its basis
* changed to be at aOrigin. This is mutually exclusive with
* OFFSET_BY_ORIGIN.
* @param aFlags INCLUDE_PRESERVE3D_ANCESTORS The computed transform will
* include the transform of any ancestors participating in the same
* 3d rendering context.
@ -4079,19 +4089,22 @@ public:
*/
enum {
OFFSET_BY_ORIGIN = 1 << 0,
INCLUDE_PRESERVE3D_ANCESTORS = 1 << 1,
INCLUDE_PERSPECTIVE = 1 << 2,
BASIS_AT_ORIGIN = 1 << 1,
INCLUDE_PRESERVE3D_ANCESTORS = 1 << 2,
INCLUDE_PERSPECTIVE = 1 << 3,
};
static Matrix4x4 GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride = nullptr);
const nsRect* aBoundsOverride = nullptr,
nsIFrame** aOutAncestor = nullptr);
static Matrix4x4 GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride = nullptr);
const nsRect* aBoundsOverride = nullptr,
nsIFrame** aOutAncestor = nullptr);
/**
* Return true when we should try to prerender the entire contents of the
* transformed frame even when it's not completely visible (yet).
@ -4171,7 +4184,8 @@ private:
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
uint32_t aFlags,
const nsRect* aBoundsOverride);
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor);
StoreList mStoredList;
Matrix4x4 mTransform;

View File

@ -2558,20 +2558,6 @@ nsLayoutUtils::MatrixTransformPoint(const nsPoint &aPoint,
NSFloatPixelsToAppUnits(float(image.y), aFactor));
}
void
nsLayoutUtils::PostTranslate(Matrix4x4& aTransform, const nsPoint& aOrigin, float aAppUnitsPerPixel, bool aRounded)
{
Point3D gfxOrigin =
Point3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
0.0f);
if (aRounded) {
gfxOrigin.x = NS_round(gfxOrigin.x);
gfxOrigin.y = NS_round(gfxOrigin.y);
}
aTransform.PostTranslate(gfxOrigin);
}
Matrix4x4
nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor)
{

View File

@ -912,12 +912,6 @@ public:
static TransformResult TransformRect(nsIFrame* aFromFrame, nsIFrame* aToFrame,
nsRect& aRect);
/**
* Converts app units to pixels (with optional snapping) and appends as a
* translation to aTransform.
*/
static void PostTranslate(Matrix4x4& aTransform, const nsPoint& aOrigin, float aAppUnitsPerPixel, bool aRounded);
/**
* Get the border-box of aElement's primary frame, transformed it to be
* relative to aFrame.

View File

@ -6170,7 +6170,7 @@ PresShell::MarkFramesInSubtreeApproximatelyVisible(nsIFrame* aFrame,
if (!preserves3DChildren || !child->Combines3DTransformWithAncestors()) {
const nsRect overflow = child->GetVisualOverflowRectRelativeToSelf();
nsRect out;
if (nsDisplayTransform::UntransformRect(r, overflow, child, &out)) {
if (nsDisplayTransform::UntransformRect(r, overflow, child, nsPoint(0,0), &out)) {
r = out;
} else {
r.SetEmpty();

View File

@ -2249,7 +2249,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
this)) {
dirtyRect = overflow;
} else {
if (overflow.IsEmpty() && !Extend3DContext()) {
if (overflow.IsEmpty()) {
return;
}
@ -2261,7 +2261,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
nsRect untransformedDirtyRect;
if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this,
&untransformedDirtyRect)) {
nsPoint(0,0), &untransformedDirtyRect, true)) {
dirtyRect = untransformedDirtyRect;
} else {
NS_WARNING("Unable to untransform dirty rect!");
@ -5356,16 +5356,15 @@ nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
int32_t scaleFactor = PresContext()->AppUnitsPerDevPixel();
Matrix4x4 result = nsDisplayTransform::GetResultingTransformMatrix(this,
nsPoint(0,0), scaleFactor,
nsDisplayTransform::INCLUDE_PERSPECTIVE|nsDisplayTransform::OFFSET_BY_ORIGIN,
nullptr);
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(this);
nsPoint(0, 0), scaleFactor,
nsDisplayTransform::INCLUDE_PERSPECTIVE|nsDisplayTransform::BASIS_AT_ORIGIN,
nullptr, aOutAncestor);
// XXXjwatt: seems like this will double count offsets in the face of preserve-3d:
nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
/* Combine the raw transform with a translation to our parent. */
result.PostTranslate(NSAppUnitsToFloatPixels(delta.x, scaleFactor),
NSAppUnitsToFloatPixels(delta.y, scaleFactor),
0.0f);
return result;
}
@ -7831,7 +7830,8 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform,
nsRect u;
bool doTransform = aApplyTransform && aFrame->IsTransformed();
if (doTransform) {
u = nsDisplayTransform::TransformRect(bounds, aFrame, &bounds);
u = nsDisplayTransform::TransformRect(bounds, aFrame,
nsPoint(0, 0), &bounds);
} else {
u = bounds;
}
@ -7903,7 +7903,8 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform,
// with 2-D transforms, though it does match the way we handle
// overflow areas in preserve-3d 3-D scenes.
if (doTransform && !child->Combines3DTransformWithAncestors()) {
childRect = nsDisplayTransform::TransformRect(childRect, aFrame, &bounds);
childRect = nsDisplayTransform::TransformRect(childRect, aFrame,
nsPoint(0, 0), &bounds);
}
u.UnionRectEdges(u, childRect);
}
@ -7969,7 +7970,7 @@ ComputeAndIncludeOutlineArea(nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas,
break;
}
if (parent->IsTransformed() && !f->Combines3DTransformWithAncestors()) {
r = nsDisplayTransform::TransformRect(r, parent);
r = nsDisplayTransform::TransformRect(r, parent, nsPoint(0, 0));
}
}
@ -8118,51 +8119,32 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
bool hasTransform = IsTransformed();
nsSize oldSize = aOldSize ? *aOldSize : mRect.Size();
bool sizeChanged = (oldSize != aNewSize);
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
*/
SetSize(aNewSize);
if (ChildrenHavePerspective() && sizeChanged) {
nsRect newBounds(nsPoint(0, 0), aNewSize);
RecomputePerspectiveChildrenOverflow(this);
}
if (hasTransform) {
Properties().Set(nsIFrame::PreTransformOverflowAreasProperty(),
new nsOverflowAreas(aOverflowAreas));
if (Combines3DTransformWithAncestors()) {
/* If we're a preserve-3d leaf frame, then our pre-transform overflow should be correct. Our
* post-transform overflow is empty though, because we only contribute to the overflow area
* of the preserve-3d root frame.
* If we're an intermediate frame then the pre-transform overflow should contain all our
* non-preserve-3d children, which is what we want. Again we have no post-transform overflow.
*/
aOverflowAreas.SetAllTo(nsRect());
} else {
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, this);
}
/* If we're the root of the 3d context, then we want to include the overflow areas of all
* the participants. This won't have happened yet as the code above set their overflow
* area to empty. Manually collect these overflow areas now.
*/
if (Extend3DContext()) {
ComputePreserve3DChildrenOverflow(aOverflowAreas);
}
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
*/
nsRect newBounds(nsPoint(0, 0), aNewSize);
// Transform affects both overflow areas.
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
}
if (Extend3DContext()) {
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
} else if (sizeChanged && ChildrenHavePerspective()) {
RecomputePerspectiveChildrenOverflow(this, &newBounds);
}
} else {
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
if (ChildrenHavePerspective() && sizeChanged) {
nsRect newBounds(nsPoint(0, 0), aNewSize);
RecomputePerspectiveChildrenOverflow(this, &newBounds);
}
}
/* Revert the size change in case some caller is depending on this. */
SetSize(oldSize);
bool anyOverflowChanged;
if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
anyOverflowChanged = SetOverflowAreas(aOverflowAreas);
@ -8177,8 +8159,13 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
}
void
nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame)
nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds)
{
// Children may check our size when getting our transform, make sure it's valid.
nsSize oldSize = GetSize();
if (aBounds) {
SetSize(aBounds->Size());
}
nsIFrame::ChildListIterator lists(this);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
@ -8205,19 +8192,87 @@ nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame)
// style context. We must find any descendant frames using our size
// (by recursing into frames that have the same containing block)
// to update their overflow rects too.
child->RecomputePerspectiveChildrenOverflow(aStartFrame);
child->RecomputePerspectiveChildrenOverflow(aStartFrame, nullptr);
}
}
}
// Restore our old size just in case something depends on this elesewhere.
SetSize(oldSize);
}
/* The overflow rects for leaf nodes in a preserve-3d hierarchy depends on
* the mRect value for their parents (since we use their transform, and transform
* depends on this for transform-origin etc). These weren't necessarily correct
* when we reflowed initially, so walk over all preserve-3d children and repeat the
* overflow calculation.
*/
static void
RecomputePreserve3DChildrenOverflow(nsIFrame* aFrame, const nsRect* aBounds)
{
// Children may check our size when getting our transform, make sure it's valid.
nsSize oldSize = aFrame->GetSize();
if (aBounds) {
aFrame->SetSize(aBounds->Size());
}
nsIFrame::ChildListIterator lists(aFrame);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
if (!child->FrameMaintainsOverflow()) {
continue; // frame does not maintain overflow rects
}
if (child->Extend3DContext()) {
RecomputePreserve3DChildrenOverflow(child, nullptr);
} else if (child->Combines3DTransformWithAncestors()) {
nsOverflowAreas* overflow =
static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
nsRect bounds(nsPoint(0, 0), child->GetSize());
if (overflow) {
nsOverflowAreas overflowCopy = *overflow;
child->FinishAndStoreOverflow(overflowCopy, bounds.Size());
} else {
nsOverflowAreas boundsOverflow;
boundsOverflow.SetAllTo(bounds);
child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
}
}
}
}
// Restore our old size just in case something depends on this elesewhere.
aFrame->SetSize(oldSize);
// Only repeat computing our overflow in recursive calls since the initial caller is still
// in the middle of doing this and we don't want an infinite loop.
if (!aBounds) {
nsOverflowAreas* overflow =
static_cast<nsOverflowAreas*>(aFrame->Properties().Get(nsIFrame::InitialOverflowProperty()));
nsRect bounds(nsPoint(0, 0), aFrame->GetSize());
if (overflow) {
nsOverflowAreas overflowCopy = *overflow;
overflowCopy.UnionAllWith(bounds);
aFrame->FinishAndStoreOverflow(overflowCopy, bounds.Size());
} else {
nsOverflowAreas boundsOverflow;
boundsOverflow.SetAllTo(bounds);
aFrame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
}
}
}
void
nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas)
nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds)
{
// Find all descendants that participate in the 3d context, and include their overflow.
// These descendants have an empty overflow, so won't have been included in the normal
// overflow calculation. Any children that don't participate have normal overflow,
// so will have been included already.
// When we are preserving 3d we need to iterate over all children separately.
// If the child also preserves 3d then their overflow will already been in our
// coordinate space, otherwise we need to transform.
// If we're the top frame in a preserve 3d chain then we need to recalculate the overflow
// areas of all our children since they will have used our size/offset which was invalid at
// the time.
if (!Combines3DTransformWithAncestors()) {
RecomputePreserve3DChildrenOverflow(this, &aBounds);
}
nsRect childVisual;
nsRect childScrollable;
@ -8226,28 +8281,27 @@ nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas)
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
// If this child participates in the 3d context, then take the pre-transform
// region (which contains all descendants that aren't participating in the 3d context)
// and transform it into the 3d context root coordinate space.
nsPoint offset = child->GetPosition();
nsRect visual = child->GetVisualOverflowRect();
nsRect scrollable = child->GetScrollableOverflowRect();
visual.MoveBy(offset);
scrollable.MoveBy(offset);
if (child->Combines3DTransformWithAncestors()) {
nsOverflowAreas childOverflow = child->GetOverflowAreasRelativeToSelf();
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = childOverflow.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, child);
}
aOverflowAreas.UnionWith(childOverflow);
// If this child also extends the 3d context, then recurse into it
// looking for more participants.
if (child->Extend3DContext()) {
child->ComputePreserve3DChildrenOverflow(aOverflowAreas);
}
childVisual = childVisual.Union(visual);
childScrollable = childScrollable.Union(scrollable);
} else {
childVisual =
childVisual.Union(nsDisplayTransform::TransformRect(visual,
this, nsPoint(0,0), &aBounds));
childScrollable =
childScrollable.Union(nsDisplayTransform::TransformRect(scrollable,
this, nsPoint(0,0), &aBounds));
}
}
}
aOverflowAreas.Overflow(eVisualOverflow) = aOverflowAreas.Overflow(eVisualOverflow).Union(childVisual);
aOverflowAreas.Overflow(eScrollableOverflow) = aOverflowAreas.Overflow(eScrollableOverflow).Union(childScrollable);
}
uint32_t

View File

@ -2799,7 +2799,7 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
if (mOuter->ChildrenHavePerspective()) {
// The overflow areas of descendants may depend on the scroll position,
// so ensure they get updated.
mOuter->RecomputePerspectiveChildrenOverflow(mOuter);
mOuter->RecomputePerspectiveChildrenOverflow(mOuter, nullptr);
}
ScheduleSyntheticMouseMove();

View File

@ -1431,13 +1431,10 @@ public:
bool ChildrenHavePerspective() const;
/**
* Includes the overflow area of all descendants that participate in the current
* 3d context into aOverflowAreas.
*/
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
// Calculate the overflow size of all child frames, taking preserve-3d into account
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame, const nsRect* aBounds);
/**
* Returns the number of ancestors between this and the root of our frame tree