зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
86c41a5975
Коммит
8e44d6c57b
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче