From 7008f05a27c04d6a2de67df32d6e65968e154db7 Mon Sep 17 00:00:00 2001 From: "bzbarsky@mit.edu" Date: Tue, 15 May 2007 20:22:45 -0700 Subject: [PATCH] Make sure FrameNeedsReflow() is not called during reflow, and remove thewasDirty asserts and O(N^2) check for existing reflow root in the list. Bug379904, r=roc, sr=dbaron --- layout/base/nsPresShell.cpp | 20 ++++++++++--------- .../xul/base/src/tree/src/nsTreeBodyFrame.cpp | 20 +++++++++++++------ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index c381ceebbb31..189945b7c0e0 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -2541,6 +2541,8 @@ PresShell::sPaintSuppressionCallback(nsITimer *aTimer, void* aPresShell) NS_IMETHODIMP PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) { + NS_PRECONDITION(!mIsReflowing, "Shouldn't be in reflow here!"); + // 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, // ignore them altogether. @@ -2569,10 +2571,11 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) { // Kick off a top-down reflow AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow); - // XXXldb Set mIsReflowing (and unset it later)? + mIsReflowing = PR_TRUE; mDirtyRoots.RemoveElement(rootFrame); DoReflow(rootFrame); + mIsReflowing = PR_FALSE; } DidCauseReflow(); @@ -2648,7 +2651,12 @@ PresShell::NotifyDestroyingFrame(nsIFrame* aFrame) if (!mIgnoreFrameDestruction) { mFrameConstructor->NotifyDestroyingFrame(aFrame); - mDirtyRoots.RemoveElement(aFrame); + for (PRInt32 idx = mDirtyRoots.Count(); idx; ) { + --idx; + if (mDirtyRoots[idx] == aFrame) { + mDirtyRoots.RemoveElementAt(idx); + } + } // Notify the frame manager FrameManager()->NotifyDestroyingFrame(aFrame); @@ -3135,8 +3143,7 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN, "Unexpected bits being added"); - // XXX Add this assertion at some point!? nsSliderFrame triggers it a lot. - //NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow"); + NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow"); // If we've not yet done the initial reflow, then don't bother // enqueuing a reflow command yet. @@ -3218,11 +3225,6 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, if (FRAME_IS_REFLOW_ROOT(f) || !f->GetParent()) { // we've hit a reflow root or the root frame if (!wasDirty) { - // Remove existing entries so we don't get duplicates, - // NotifyDestroyingFrame() only removes one entry, bug 366320. - while (NS_UNLIKELY(mDirtyRoots.RemoveElement(f))) { - NS_ERROR("wasDirty lied"); - } mDirtyRoots.AppendElement(f); } #ifdef DEBUG diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index e93958f112bf..ef1dd16ef2f6 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -451,6 +451,7 @@ nsTreeBodyFrame::ReflowFinished() } InvalidateScrollbars(parts); + UpdateScrollbars(parts); CheckOverflow(parts); } @@ -511,14 +512,21 @@ NS_IMETHODIMP nsTreeBodyFrame::SetView(nsITreeView * aView) mView->SetTree(mTreeBoxObject); mView->GetRowCount(&mRowCount); - ScrollParts parts = GetScrollParts(); - // The scrollbar will need to be updated. - InvalidateScrollbars(parts); + PRBool isInReflow; + PresContext()->PresShell()->IsReflowLocked(&isInReflow); + if (!isInReflow) { + ScrollParts parts = GetScrollParts(); + // The scrollbar will need to be updated. + InvalidateScrollbars(parts); - // Reset scrollbar position. - UpdateScrollbars(parts); + // Reset scrollbar position. + UpdateScrollbars(parts); - CheckOverflow(parts); + CheckOverflow(parts); + } else if (!mReflowCallbackPosted) { + mReflowCallbackPosted = PR_TRUE; + PresContext()->PresShell()->PostReflowCallback(this); + } } return NS_OK;