Bug 1577258 - Streamline the shrink-wrapping resize reflow code. r=botond

Now that this code path is on its own, we can write more straight-forward code.



Depends on D43799

Differential Revision: https://phabricator.services.mozilla.com/D43800

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-09-12 21:27:06 +00:00
Родитель 86c41a5975
Коммит 8e44d6c57b
1 изменённых файлов: 49 добавлений и 104 удалений

Просмотреть файл

@ -1913,8 +1913,19 @@ nsresult PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
return NS_OK; return NS_OK;
} }
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame(); MOZ_ASSERT(!mPresContext->SuppressingResizeReflow(),
if (!rootFrame) { "Can't suppress resize reflow and shrink-wrap at the same time");
// Make sure that style is flushed before setting the pres context
// VisibleArea.
//
// Otherwise we may end up with bogus viewport units resolved against the
// unconstrained bsize, or restyling the whole document resolving viewport
// units against targetWidth, which may end up doing wasteful work.
mDocument->FlushPendingNotifications(FlushType::Frames);
nsIFrame* rootFrame = GetRootFrame();
if (mIsDestroying || !rootFrame) {
// If we don't have a root frame yet, that means we haven't had our initial // If we don't have a root frame yet, that means we haven't had our initial
// reflow... If that's the case, and aWidth or aHeight is unconstrained, // reflow... If that's the case, and aWidth or aHeight is unconstrained,
// ignore them altogether. // ignore them altogether.
@ -1931,123 +1942,57 @@ nsresult PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
} }
WritingMode wm = rootFrame->GetWritingMode(); WritingMode wm = rootFrame->GetWritingMode();
const bool shrinkToFit = !!(aOptions & ResizeReflowOptions::BSizeLimit);
MOZ_ASSERT(shrinkToFit ||
(wm.IsVertical() ? aWidth : aHeight) != NS_UNCONSTRAINEDSIZE,
"unconstrained bsize only usable with eBSizeLimit");
MOZ_ASSERT((wm.IsVertical() ? aHeight : aWidth) != NS_UNCONSTRAINEDSIZE, MOZ_ASSERT((wm.IsVertical() ? aHeight : aWidth) != NS_UNCONSTRAINEDSIZE,
"unconstrained isize not allowed"); "unconstrained isize not allowed");
bool isBSizeChanging =
wm.IsVertical() ? aOldWidth != aWidth : aOldHeight != aHeight;
nscoord targetWidth = aWidth; nscoord targetWidth = aWidth;
nscoord targetHeight = aHeight; nscoord targetHeight = aHeight;
if (wm.IsVertical()) {
if (shrinkToFit) { targetWidth = NS_UNCONSTRAINEDSIZE;
if (wm.IsVertical()) { } else {
targetWidth = NS_UNCONSTRAINEDSIZE; targetHeight = NS_UNCONSTRAINEDSIZE;
} else {
targetHeight = NS_UNCONSTRAINEDSIZE;
}
isBSizeChanging = true;
} }
const bool suppressingResizeReflow = mPresContext->SetVisibleArea(nsRect(0, 0, targetWidth, targetHeight));
GetPresContext()->SuppressingResizeReflow(); // XXX Do a full invalidate at the beginning so that invalidates along
// the way don't have region accumulation issues?
RefPtr<nsViewManager> viewManager = mViewManager; // For height:auto BSizes (i.e. layout-controlled), descendant
if (!suppressingResizeReflow && shrinkToFit) { // intrinsic sizes can't depend on them. So the only other case is
// Make sure that style is flushed before setting the pres context // viewport-controlled BSizes which we handle here.
// VisibleArea if we're shrinking to fit. nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize(rootFrame);
//
// Otherwise we may end up with bogus viewport units resolved against the
// unconstrained bsize, or restyling the whole document resolving viewport
// units against targetWidth, which may end up doing wasteful work.
mDocument->FlushPendingNotifications(FlushType::Frames);
}
if (!mIsDestroying) { {
mPresContext->SetVisibleArea(nsRect(0, 0, targetWidth, targetHeight)); nsAutoCauseReflowNotifier crNotifier(this);
} WillDoReflow();
if (!mIsDestroying && !suppressingResizeReflow) { // Kick off a top-down reflow
if (!shrinkToFit) { AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
// Flush styles _now_ (with the correct visible area) if not computing the nsViewManager::AutoDisableRefresh refreshBlocker(mViewManager);
// shrink-to-fit size.
//
// We've asserted above that sizes are not unconstrained, so this is going
// to be the final size, which means that we'll get the (correct) final
// styles now, and avoid a further potentially-wasteful full recascade on
// the next flush.
mDocument->FlushPendingNotifications(FlushType::Frames);
}
rootFrame = mFrameConstructor->GetRootFrame(); mDirtyRoots.Remove(rootFrame);
if (!mIsDestroying && rootFrame) { DoReflow(rootFrame, true, nullptr);
// XXX Do a full invalidate at the beginning so that invalidates along
// the way don't have region accumulation issues?
if (isBSizeChanging) { const bool reflowAgain =
// For BSize changes driven by style, RestyleManager handles this. wm.IsVertical() ? mPresContext->GetVisibleArea().width > aWidth
// For height:auto BSizes (i.e. layout-controlled), descendant : mPresContext->GetVisibleArea().height > aHeight;
// intrinsic sizes can't depend on them. So the only other case is
// viewport-controlled BSizes which we handle here.
nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize(rootFrame);
}
{ if (reflowAgain) {
nsAutoCauseReflowNotifier crNotifier(this); mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
WillDoReflow(); DoReflow(rootFrame, true, nullptr);
// Kick off a top-down reflow
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
nsViewManager::AutoDisableRefresh refreshBlocker(viewManager);
mDirtyRoots.Remove(rootFrame);
DoReflow(rootFrame, true, nullptr);
if (shrinkToFit) {
const bool reflowAgain =
wm.IsVertical() ? mPresContext->GetVisibleArea().width > aWidth
: mPresContext->GetVisibleArea().height > aHeight;
if (reflowAgain) {
mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
DoReflow(rootFrame, true, nullptr);
}
}
}
// the first DoReflow above should've set our bsize if it was
// NS_UNCONSTRAINEDSIZE, and the isize shouldn't be NS_UNCONSTRAINEDSIZE
// anyway
NS_ASSERTION(mPresContext->GetVisibleArea().width != NS_UNCONSTRAINEDSIZE,
"width should not be NS_UNCONSTRAINEDSIZE after reflow");
NS_ASSERTION(
mPresContext->GetVisibleArea().height != NS_UNCONSTRAINEDSIZE,
"height should not be NS_UNCONSTRAINEDSIZE after reflow");
DidDoReflow(true);
} }
} }
rootFrame = mFrameConstructor->GetRootFrame(); DidDoReflow(true);
if (rootFrame) {
wm = rootFrame->GetWritingMode(); // the reflow above should've set our bsize if it was NS_UNCONSTRAINEDSIZE,
// reflow did not happen; if the reflow happened, our bsize should not be // and the isize shouldn't be NS_UNCONSTRAINEDSIZE anyway.
// NS_UNCONSTRAINEDSIZE because DoReflow will fix it up to the same values MOZ_DIAGNOSTIC_ASSERT(
// as below mPresContext->GetVisibleArea().width != NS_UNCONSTRAINEDSIZE,
if (wm.IsVertical()) { "width should not be NS_UNCONSTRAINEDSIZE after reflow");
if (mPresContext->GetVisibleArea().width == NS_UNCONSTRAINEDSIZE) { MOZ_DIAGNOSTIC_ASSERT(
mPresContext->SetVisibleArea( mPresContext->GetVisibleArea().height != NS_UNCONSTRAINEDSIZE,
nsRect(0, 0, rootFrame->GetRect().width, aHeight)); "height should not be NS_UNCONSTRAINEDSIZE after reflow");
}
} else {
if (mPresContext->GetVisibleArea().height == NS_UNCONSTRAINEDSIZE) {
mPresContext->SetVisibleArea(
nsRect(0, 0, aWidth, rootFrame->GetRect().height));
}
}
}
postResizeEventIfNeeded(); postResizeEventIfNeeded();
return NS_OK; // XXX this needs to be real. MMP return NS_OK; // XXX this needs to be real. MMP