Bug 911786 - Part 2: Reapply relative positioning when moving frames without reflowing them. r=dholbert
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -2577,35 +2577,31 @@ nsBlockFrame::SlideLine(nsBlockReflowSta
// Adjust the frames in the line
nsIFrame* kid = aLine->mFirstChild;
if (!kid) {
return;
}
if (aLine->IsBlock()) {
if (aDY) {
- nsPoint p = kid->GetPosition();
- p.y += aDY;
- kid->SetPosition(p);
+ kid->MovePositionBy(nsPoint(0, aDY));
}
// Make sure the frame's view and any child views are updated
::PlaceFrameView(kid);
}
else {
// Adjust the Y coordinate of the frames in the line.
// Note: we need to re-position views even if aDY is 0, because
// one of our parent frames may have moved and so the view's position
// relative to its parent may have changed
int32_t n = aLine->GetChildCount();
while (--n >= 0) {
if (aDY) {
- nsPoint p = kid->GetPosition();
- p.y += aDY;
- kid->SetPosition(p);
+ kid->MovePositionBy(nsPoint(0, aDY));
}
// Make sure the frame's view and any child views are updated
::PlaceFrameView(kid);
kid = kid->GetNextSibling();
}
}
}
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -381,18 +381,17 @@ nsBlockReflowState::RecoverFloats(nsLine
{
if (aLine->HasFloats()) {
// Place the floats into the space-manager again. Also slide
// them, just like the regular frames on the line.
nsFloatCache* fc = aLine->GetFirstFloat();
while (fc) {
nsIFrame* floatFrame = fc->mFloat;
if (aDeltaY != 0) {
- nsPoint p = floatFrame->GetPosition();
- floatFrame->SetPosition(nsPoint(p.x, p.y + aDeltaY));
+ floatFrame->MovePositionBy(nsPoint(0, aDeltaY));
nsContainerFrame::PositionFrameView(floatFrame);
nsContainerFrame::PositionChildViews(floatFrame);
}
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
nscoord tx, ty;
mFloatManager->GetTranslation(tx, ty);
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5065,16 +5065,32 @@ ComputeOutlineAndEffectsRect(nsIFrame* a
Set(nsIFrame::PreEffectsBBoxProperty(), new nsRect(r));
}
r = nsSVGIntegrationUtils::ComputePostEffectsVisualOverflowRect(aFrame, r);
}
return r;
}
+void
+nsIFrame::MovePositionBy(const nsPoint& aTranslation)
+{
+ nsPoint position = GetNormalPosition() + aTranslation;
+
+ const nsMargin* computedOffsets = nullptr;
+ if (IsRelativelyPositioned()) {
+ computedOffsets = static_cast<nsMargin*>
+ (Properties().Get(nsIFrame::ComputedOffsetProperty()));
+ }
+ nsHTMLReflowState::ApplyRelativePositioning(this, computedOffsets ?
+ *computedOffsets : nsMargin(),
+ &position);
+ SetPosition(position);
+}
+
nsPoint
nsIFrame::GetNormalPosition() const
{
// It might be faster to first check
// StyleDisplay()->IsRelativelyPositionedStyle().
nsPoint* normalPosition = static_cast<nsPoint*>
(Properties().Get(NormalPositionProperty()));
if (normalPosition) {
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -862,16 +862,23 @@ public:
}
}
void SetSize(const nsSize& aSize) {
SetRect(nsRect(mRect.TopLeft(), aSize));
}
void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
/**
+ * Move the frame, accounting for relative positioning. Use this when
+ * adjusting the frame's position by a known amount, to properly update its
+ * saved normal position (see GetNormalPosition below).
+ */
+ void MovePositionBy(const nsPoint& aTranslation);
+
+ /**
* Return frame's position without relative positioning
*/
nsPoint GetNormalPosition() const;
virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
{ return aChild->GetPosition(); }
nsPoint GetPositionIgnoringScrolling() {
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -2191,19 +2191,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
}
if (maxBottomBoxHeight > mMaxBottomBoxHeight) {
mMaxBottomBoxHeight = maxBottomBoxHeight;
}
}
static void SlideSpanFrameRect(nsIFrame* aFrame, nscoord aDeltaWidth)
{
- nsRect r = aFrame->GetRect();
- r.x -= aDeltaWidth;
- aFrame->SetRect(r);
+ aFrame->MovePositionBy(nsPoint(-aDeltaWidth, 0));
}
bool
nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
nscoord* aDeltaWidth)
{
#ifndef IBMBIDI
// XXX what about NS_STYLE_DIRECTION_RTL?