Bug 703241. PresShell::DoScrollContentIntoView and PresShell::ScrollFrameRectIntoView should take transforms into account. r=matspal

This commit is contained in:
Robert O'Callahan
2012-06-22 17:06:49 +12:00
parent 6cd6fcb5df
commit be70e1e702
3 changed files with 57 additions and 8 deletions

View File

@@ -2964,8 +2964,8 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
nsAutoLineIterator& aLines,
PRInt32& aCurLine)
{
nsRect frameBounds = aFrame->GetRect() +
aFrame->GetParent()->GetOffsetTo(aContainerFrame);
nsIFrame* frame = aFrame;
nsRect frameBounds = nsRect(nsPoint(0, 0), aFrame->GetSize());
// If this is an inline frame and either the bounds height is 0 (quirks
// layout model) or aUseWholeLineHeightForInlines is set, we need to
@@ -3001,7 +3001,8 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
if (NS_SUCCEEDED(aLines->GetLine(index, &trash1, &trash2,
lineBounds, &trash3))) {
lineBounds += f->GetOffsetTo(aContainerFrame);
frameBounds += frame->GetOffsetTo(f);
frame = f;
if (lineBounds.y < frameBounds.y) {
frameBounds.height = frameBounds.YMost() - lineBounds.y;
frameBounds.y = lineBounds.y;
@@ -3012,14 +3013,17 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
}
}
nsRect transformedBounds = nsLayoutUtils::TransformFrameRectToAncestor(frame,
frameBounds, aContainerFrame);
if (aHaveRect) {
// We can't use nsRect::UnionRect since it drops empty rects on
// the floor, and we need to include them. (Thus we need
// aHaveRect to know when to drop the initial value on the floor.)
aRect.UnionRectEdges(aRect, frameBounds);
aRect.UnionRectEdges(aRect, transformedBounds);
} else {
aHaveRect = true;
aRect = frameBounds;
aRect = transformedBounds;
}
}
@@ -3315,8 +3319,14 @@ PresShell::ScrollFrameRectIntoView(nsIFrame* aFrame,
break;
}
}
rect += container->GetPosition();
nsIFrame* parent = container->GetParent();
nsIFrame* parent;
if (container->IsTransformed()) {
container->GetTransformMatrix(nsnull, &parent);
rect = nsLayoutUtils::TransformFrameRectToAncestor(container, rect, parent);
} else {
rect += container->GetPosition();
parent = container->GetParent();
}
if (!parent && !(aFlags & nsIPresShell::SCROLL_NO_PARENT_FRAMES)) {
nsPoint extraOffset(0,0);
parent = nsLayoutUtils::GetCrossDocParentFrame(container, &extraOffset);

View File

@@ -40,6 +40,29 @@
<div style='height:400px;'></div>">
</iframe>
</div>
<div id="c5" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:0;">
<div style="-moz-transform:translateY(400px); transform:translateY(400px)">
<span id="target5" style="display:inline-block; vertical-align:top; height:20px;">target</span>
</div>
<div style="height:800px;"></div>
</div>
<div id="c6" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:200px;">
<div style="height:200px"></div>
<div style="height:100px; -moz-transform:scale(2); transform:scale(2)">
<span id="target6" style="display:inline-block; vertical-align:top; height:20px;">target</span>
</div>
<div style="height:800px;"></div>
</div>
<div id="c7" style="overflow-y:scroll; width:200px; height:200px; position:absolute; top:400px; left:400px;">
<div style="overflow:auto; height:200px; -moz-transform:translateY(400px); transform:translateY(400px)">
<div style="height:200px;"></div>
<div>
<span id="target7" style="display:inline-block; vertical-align:top; height:20px;">target</span>
</div>
<div style="height:800px;"></div>
</div>
<div style="height:800px;"></div>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
@@ -101,6 +124,18 @@ function doTest() {
// visible.
testCollapsed("4", -1, 1000, 400);
// Test that scrolling a translated element into view takes
// account of the transform.
testCollapsed("5", 0, 0, 400);
// Test that scrolling a scaled element into view takes
// account of the transform.
testCollapsed("6", 0, 0, 150);
// Test that scrolling an element with a translated, scrolling container
// into view takes account of the transform.
testCollapsed("7", 0, 0, 400);
SimpleTest.finish();
}

View File

@@ -1960,7 +1960,11 @@ public:
* @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
* all ancestors (including across documents) will be traversed.
* @param aOutAncestor [out] The ancestor frame the frame has chosen. If
* this frame has no ancestor, *aOutAncestor will be set to null.
* this frame has no ancestor, *aOutAncestor will be set to null. If
* this frame is not a root frame, then *aOutAncestor will be in the same
* document as this frame. If this frame IsTransformed(), then *aOutAncestor
* will be the parent frame (if not preserve-3d) or the nearest non-transformed
* ancestor (if preserve-3d).
* @return A gfxMatrix that converts points in this frame's coordinate space
* into points in aOutAncestor's coordinate space.
*/