diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 1dadbfe38c7..85a78b27f44 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -77,6 +77,7 @@ #include "nsLegendFrame.h" #include "nsTitleFrame.h" #include "nsIContentIterator.h" +#include "nsBoxLayoutState.h" #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" @@ -9043,31 +9044,29 @@ StyleChangeReflow(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIAtom * aAttribute) { - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); + + // Is it a box? If so we can coelesce. + nsresult rv; + nsCOMPtr box = do_QueryInterface(aFrame, &rv); + if (NS_SUCCEEDED(rv) && box) { + nsBoxLayoutState state(aPresContext); + box->MarkStyleChange(state); + } else { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsIReflowCommand* reflowCmd; + nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, + nsIReflowCommand::StyleChanged, + nsnull, + aAttribute); - nsIReflowCommand* reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, - nsIReflowCommand::StyleChanged, - nsnull, - aAttribute); - if (NS_SUCCEEDED(rv)) { - shell->AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + if (NS_SUCCEEDED(rv)) { + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } - - /* - - nsFrameState state; - aFrame->GetFrameState(&state); - state |= NS_FRAME_IS_DIRTY; - aFrame->SetFrameState(state); - nsIFrame* parent; - aFrame->GetParent(&parent); - parent->ReflowDirtyChild(shell, aFrame); -*/ } NS_IMETHODIMP diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 82c8a5beabb..42661436f9e 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -54,6 +54,8 @@ #include "nsIURIContentListener.h" #include "nsIInterfaceRequestor.h" #include "nsIServiceManager.h" +#include "nsBoxLayoutState.h" +#include "nsIBox.h" #ifdef _WIN32 #include @@ -270,12 +272,24 @@ nsPresContext::RemapStyleAndReflow() rootFrame->GetStyleContext(&rootStyleContext); rootStyleContext->RemapStyle(this); NS_RELEASE(rootStyleContext); - - // Force a reflow of the root frame - // XXX We really should only do a reflow if a preference that affects - // formatting changed, e.g., a font change. If it's just a color change - // then we only need to repaint... - mShell->StyleChangeReflow(); + + // boxes know how to coelesce style changes. So if our root frame is a box + // then tell it to handle it. If its a block we are stuck with a full top to bottom + // reflow. -EDV + nsIFrame* child = nsnull; + rootFrame->FirstChild(this, nsnull, &child); + nsresult rv; + nsCOMPtr box = do_QueryInterface(child, &rv); + if (NS_SUCCEEDED(rv) && box) { + nsBoxLayoutState state(this); + box->MarkStyleChange(state); + } else { + // Force a reflow of the root frame + // XXX We really should only do a reflow if a preference that affects + // formatting changed, e.g., a font change. If it's just a color change + // then we only need to repaint... + mShell->StyleChangeReflow(); + } } } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index d7fafc58c51..e24b3269c4f 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -136,76 +136,6 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); #undef NOISY -//======================================================================== -#ifdef MOZ_REFLOW_PERF -class ReflowCountMgr; - -static const char * kGrandTotalsStr = "Grand Totals"; -#define NUM_REFLOW_TYPES 5 - -// Counting Class -class ReflowCounter { -public: - ReflowCounter(ReflowCountMgr * aMgr); - ~ReflowCounter(); - - void ClearTotals(); - void DisplayTotals(const char * aStr); - void DisplayHTMLTotals(const char * aStr); - - void Add(nsReflowReason aType) { mTotals[aType]++; mTotal++; } - void Add(nsReflowReason aType, PRUint32 aTotal) { mTotals[aType] += aTotal; mTotal += aTotal; } - -protected: - void DisplayTotals(PRUint32 * aArray, const char * aTitle); - void DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle); - - PRUint32 mTotals[NUM_REFLOW_TYPES]; - PRUint32 mTotal; - ReflowCountMgr * mMgr; -}; - -// Manager Class -class ReflowCountMgr { -public: - ReflowCountMgr(); - //static ReflowCountMgr * GetInstance() { return &gReflowCountMgr; } - - ~ReflowCountMgr(); - - void ClearTotals(); - void DisplayTotals(const char * aStr); - void DisplayHTMLTotals(const char * aStr); - - void Add(const char * aName, nsReflowReason aType); - ReflowCounter * LookUp(const char * aName); - - FILE * GetOutFile() { return mFD; } - -protected: - void DisplayTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); - void DisplayHTMLTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); - - static PRIntn RemoveItems(PLHashEntry *he, PRIntn i, void *arg); - void CleanUp(); - - // stdout Output Methods - static PRIntn DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg); - void DoGrandTotals(); - - // HTML Output Methods - static PRIntn DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg); - void DoGrandHTMLTotals(); - - PLHashTable * mCounts; - FILE * mFD; - - // ReflowCountMgr gReflowCountMgr; -}; -#endif -//======================================================================== - - // comment out to hide caret #define SHOW_CARET @@ -330,7 +260,6 @@ StackArena::Push() StackMark* oldMarks = mMarks; PRUint32 oldLength = mMarkLength; mMarkLength += MARK_INCREMENT; - void* marks = 0; mMarks = new StackMark[mMarkLength]; nsCRT::memcpy(mMarks, oldMarks, sizeof(StackMark)*oldLength); @@ -2127,6 +2056,12 @@ PresShell::AlreadyInQueue(nsIReflowCommand* aReflowCommand) return inQueue; } +/* +#ifdef DEBUG_evaughan +static PRInt32 gPosted = 0; +#endif +*/ + NS_IMETHODIMP PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand) { @@ -2152,6 +2087,11 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand) if (!AlreadyInQueue(aReflowCommand)) { NS_ADDREF(aReflowCommand); rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY); + /* +#ifdef DEBUG_evaughan + printf("ReflowCommandsPosted=%d\n", ++gPosted); +#endif + */ } // Kick off a reflow event if we aren't batching reflows diff --git a/layout/base/src/Makefile.in b/layout/base/src/Makefile.in index af5427229f0..911d848aef1 100644 --- a/layout/base/src/Makefile.in +++ b/layout/base/src/Makefile.in @@ -89,5 +89,5 @@ include $(topsrcdir)/config/rules.mk DEFINES += -D_IMPL_NS_LAYOUT -INCLUDES += -I$(srcdir)/../../html/base/src -I$(srcdir)/../../html/style/src +INCLUDES += -I$(srcdir)/../../html/base/src -I$(srcdir)/../../html/style/src -I$(srcdir)/../../xul/base/src diff --git a/layout/base/src/makefile.win b/layout/base/src/makefile.win index 6717e23f010..b8ee16be9aa 100644 --- a/layout/base/src/makefile.win +++ b/layout/base/src/makefile.win @@ -124,6 +124,7 @@ CPP_OBJS= \ LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor \ -I$(PUBLIC)\dom -I$(PUBLIC)\js -I$(PUBLIC)\netlib \ -I$(PUBLIC)\pref -I..\..\html\base\src -I..\..\html\style\src \ + -I..\..\xul\base\src \ -I$(PUBLIC)\lwbrk -I$(PUBLIC)\plugin LCFLAGS = \ diff --git a/layout/base/src/nsPresContext.cpp b/layout/base/src/nsPresContext.cpp index 82c8a5beabb..42661436f9e 100644 --- a/layout/base/src/nsPresContext.cpp +++ b/layout/base/src/nsPresContext.cpp @@ -54,6 +54,8 @@ #include "nsIURIContentListener.h" #include "nsIInterfaceRequestor.h" #include "nsIServiceManager.h" +#include "nsBoxLayoutState.h" +#include "nsIBox.h" #ifdef _WIN32 #include @@ -270,12 +272,24 @@ nsPresContext::RemapStyleAndReflow() rootFrame->GetStyleContext(&rootStyleContext); rootStyleContext->RemapStyle(this); NS_RELEASE(rootStyleContext); - - // Force a reflow of the root frame - // XXX We really should only do a reflow if a preference that affects - // formatting changed, e.g., a font change. If it's just a color change - // then we only need to repaint... - mShell->StyleChangeReflow(); + + // boxes know how to coelesce style changes. So if our root frame is a box + // then tell it to handle it. If its a block we are stuck with a full top to bottom + // reflow. -EDV + nsIFrame* child = nsnull; + rootFrame->FirstChild(this, nsnull, &child); + nsresult rv; + nsCOMPtr box = do_QueryInterface(child, &rv); + if (NS_SUCCEEDED(rv) && box) { + nsBoxLayoutState state(this); + box->MarkStyleChange(state); + } else { + // Force a reflow of the root frame + // XXX We really should only do a reflow if a preference that affects + // formatting changed, e.g., a font change. If it's just a color change + // then we only need to repaint... + mShell->StyleChangeReflow(); + } } } diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index 592d099a5f3..410c5fd12a4 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -285,6 +285,9 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, return Reflow(aPresContext, aDesiredSize, newState, aStatus); } break; + + default: + NS_ERROR("Unexpected Reflow Type"); } } else { aReflowState.reflowCommand->GetNext(incrementalChild); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 8613a226b0d..e6cadd57958 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -662,7 +662,11 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, y = value.ToInteger(&error); } + nsIScrollableView* s = GetScrollableView(mOuter->mPresContext); + s->RemoveScrollPositionListener(this); ScrollbarChanged(mOuter->mPresContext, x*mOnePixel, y*mOnePixel); + s->AddScrollPositionListener(this); + } } @@ -762,7 +766,11 @@ NS_IMETHODIMP nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) { PropagateDebug(aState); + PRUint32 flags = 0; + aState.GetLayoutFlags(flags); nsresult rv = mInner->Layout(aState); + aState.SetLayoutFlags(flags); + nsBox::Layout(aState); return rv; } @@ -960,68 +968,64 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) scrollable->SetLineHeight(fontHeight); - // layout the vertical and horizontal scrollbars - - - // set the scrollbars properties. Mark the scrollbars for reflow if there values change. - if (mHasVerticalScrollbar) { - nsRect vRect(clientRect); - vRect.width = vSize.width; - vRect.y = clientRect.y; - - if (mHasHorizontalScrollbar) { - vRect.height -= hSize.height; - if (!scrollBarBottom) - vRect.y += hSize.height; - } - - vRect.x = clientRect.x; - - if (scrollBarRight) - vRect.x += clientRect.width - vSize.width; - - if (vMinSize.width > vRect.width || vMinSize.height > vRect.height) { - mVScrollbarBox->Collapse(aState); - } else { - SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); - SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); - SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); - - LayoutBox(aState, mVScrollbarBox, vRect); - } - } + // layout vertical scrollbar + nsRect vRect(clientRect); + vRect.width = vSize.width; + vRect.y = clientRect.y; if (mHasHorizontalScrollbar) { - - nsRect hRect(clientRect); - hRect.height = hSize.height; - - hRect.x = clientRect.x; - - if (mHasVerticalScrollbar) { - hRect.width -= vSize.width; - if (!scrollBarRight) - hRect.x += vSize.width; - } - - hRect.y = clientRect.y; - - if (scrollBarBottom) - hRect.y += clientRect.height - hSize.height; - - - if (hMinSize.width > hRect.width || hMinSize.height > hRect.height) { - mHScrollbarBox->Collapse(aState); - } else { - SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); - SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); - SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); - - LayoutBox(aState, mHScrollbarBox, hRect); - } + vRect.height -= hSize.height; + if (!scrollBarBottom) + vRect.y += hSize.height; } - - return NS_OK; + + vRect.x = clientRect.x; + + if (scrollBarRight) + vRect.x += clientRect.width - vSize.width; + + if (mHasVerticalScrollbar) { + SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); + SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); + } + + LayoutBox(aState, mVScrollbarBox, vRect); + + if (!mHasVerticalScrollbar || (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) + mVScrollbarBox->Collapse(aState); + + + // layout horizontal scrollbar + nsRect hRect(clientRect); + hRect.height = hSize.height; + + hRect.x = clientRect.x; + + if (mHasVerticalScrollbar) { + hRect.width -= vSize.width; + if (!scrollBarRight) + hRect.x += vSize.width; + } + + hRect.y = clientRect.y; + + if (scrollBarBottom) + hRect.y += clientRect.height - hSize.height; + + if (mHasHorizontalScrollbar) { + SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); + SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); + SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + } + + LayoutBox(aState, mHScrollbarBox, hRect); + + if (!mHasHorizontalScrollbar || (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { + mHScrollbarBox->Collapse(aState); + } + + return NS_OK; } void diff --git a/layout/html/base/src/nsGfxScrollFrame.cpp b/layout/html/base/src/nsGfxScrollFrame.cpp index 8613a226b0d..e6cadd57958 100644 --- a/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/layout/html/base/src/nsGfxScrollFrame.cpp @@ -662,7 +662,11 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, y = value.ToInteger(&error); } + nsIScrollableView* s = GetScrollableView(mOuter->mPresContext); + s->RemoveScrollPositionListener(this); ScrollbarChanged(mOuter->mPresContext, x*mOnePixel, y*mOnePixel); + s->AddScrollPositionListener(this); + } } @@ -762,7 +766,11 @@ NS_IMETHODIMP nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) { PropagateDebug(aState); + PRUint32 flags = 0; + aState.GetLayoutFlags(flags); nsresult rv = mInner->Layout(aState); + aState.SetLayoutFlags(flags); + nsBox::Layout(aState); return rv; } @@ -960,68 +968,64 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) scrollable->SetLineHeight(fontHeight); - // layout the vertical and horizontal scrollbars - - - // set the scrollbars properties. Mark the scrollbars for reflow if there values change. - if (mHasVerticalScrollbar) { - nsRect vRect(clientRect); - vRect.width = vSize.width; - vRect.y = clientRect.y; - - if (mHasHorizontalScrollbar) { - vRect.height -= hSize.height; - if (!scrollBarBottom) - vRect.y += hSize.height; - } - - vRect.x = clientRect.x; - - if (scrollBarRight) - vRect.x += clientRect.width - vSize.width; - - if (vMinSize.width > vRect.width || vMinSize.height > vRect.height) { - mVScrollbarBox->Collapse(aState); - } else { - SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); - SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); - SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); - - LayoutBox(aState, mVScrollbarBox, vRect); - } - } + // layout vertical scrollbar + nsRect vRect(clientRect); + vRect.width = vSize.width; + vRect.y = clientRect.y; if (mHasHorizontalScrollbar) { - - nsRect hRect(clientRect); - hRect.height = hSize.height; - - hRect.x = clientRect.x; - - if (mHasVerticalScrollbar) { - hRect.width -= vSize.width; - if (!scrollBarRight) - hRect.x += vSize.width; - } - - hRect.y = clientRect.y; - - if (scrollBarBottom) - hRect.y += clientRect.height - hSize.height; - - - if (hMinSize.width > hRect.width || hMinSize.height > hRect.height) { - mHScrollbarBox->Collapse(aState); - } else { - SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); - SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); - SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); - - LayoutBox(aState, mHScrollbarBox, hRect); - } + vRect.height -= hSize.height; + if (!scrollBarBottom) + vRect.y += hSize.height; } - - return NS_OK; + + vRect.x = clientRect.x; + + if (scrollBarRight) + vRect.x += clientRect.width - vSize.width; + + if (mHasVerticalScrollbar) { + SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight)); + SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight, PR_FALSE); + } + + LayoutBox(aState, mVScrollbarBox, vRect); + + if (!mHasVerticalScrollbar || (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) + mVScrollbarBox->Collapse(aState); + + + // layout horizontal scrollbar + nsRect hRect(clientRect); + hRect.height = hSize.height; + + hRect.x = clientRect.x; + + if (mHasVerticalScrollbar) { + hRect.width -= vSize.width; + if (!scrollBarRight) + hRect.x += vSize.width; + } + + hRect.y = clientRect.y; + + if (scrollBarBottom) + hRect.y += clientRect.height - hSize.height; + + if (mHasHorizontalScrollbar) { + SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX); + SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8)); + SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + } + + LayoutBox(aState, mHScrollbarBox, hRect); + + if (!mHasHorizontalScrollbar || (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { + mHScrollbarBox->Collapse(aState); + } + + return NS_OK; } void diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index d7fafc58c51..e24b3269c4f 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -136,76 +136,6 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); #undef NOISY -//======================================================================== -#ifdef MOZ_REFLOW_PERF -class ReflowCountMgr; - -static const char * kGrandTotalsStr = "Grand Totals"; -#define NUM_REFLOW_TYPES 5 - -// Counting Class -class ReflowCounter { -public: - ReflowCounter(ReflowCountMgr * aMgr); - ~ReflowCounter(); - - void ClearTotals(); - void DisplayTotals(const char * aStr); - void DisplayHTMLTotals(const char * aStr); - - void Add(nsReflowReason aType) { mTotals[aType]++; mTotal++; } - void Add(nsReflowReason aType, PRUint32 aTotal) { mTotals[aType] += aTotal; mTotal += aTotal; } - -protected: - void DisplayTotals(PRUint32 * aArray, const char * aTitle); - void DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle); - - PRUint32 mTotals[NUM_REFLOW_TYPES]; - PRUint32 mTotal; - ReflowCountMgr * mMgr; -}; - -// Manager Class -class ReflowCountMgr { -public: - ReflowCountMgr(); - //static ReflowCountMgr * GetInstance() { return &gReflowCountMgr; } - - ~ReflowCountMgr(); - - void ClearTotals(); - void DisplayTotals(const char * aStr); - void DisplayHTMLTotals(const char * aStr); - - void Add(const char * aName, nsReflowReason aType); - ReflowCounter * LookUp(const char * aName); - - FILE * GetOutFile() { return mFD; } - -protected: - void DisplayTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); - void DisplayHTMLTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); - - static PRIntn RemoveItems(PLHashEntry *he, PRIntn i, void *arg); - void CleanUp(); - - // stdout Output Methods - static PRIntn DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg); - void DoGrandTotals(); - - // HTML Output Methods - static PRIntn DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg); - void DoGrandHTMLTotals(); - - PLHashTable * mCounts; - FILE * mFD; - - // ReflowCountMgr gReflowCountMgr; -}; -#endif -//======================================================================== - - // comment out to hide caret #define SHOW_CARET @@ -330,7 +260,6 @@ StackArena::Push() StackMark* oldMarks = mMarks; PRUint32 oldLength = mMarkLength; mMarkLength += MARK_INCREMENT; - void* marks = 0; mMarks = new StackMark[mMarkLength]; nsCRT::memcpy(mMarks, oldMarks, sizeof(StackMark)*oldLength); @@ -2127,6 +2056,12 @@ PresShell::AlreadyInQueue(nsIReflowCommand* aReflowCommand) return inQueue; } +/* +#ifdef DEBUG_evaughan +static PRInt32 gPosted = 0; +#endif +*/ + NS_IMETHODIMP PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand) { @@ -2152,6 +2087,11 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand) if (!AlreadyInQueue(aReflowCommand)) { NS_ADDREF(aReflowCommand); rv = (mReflowCommands.AppendElement(aReflowCommand) ? NS_OK : NS_ERROR_OUT_OF_MEMORY); + /* +#ifdef DEBUG_evaughan + printf("ReflowCommandsPosted=%d\n", ++gPosted); +#endif + */ } // Kick off a reflow event if we aren't batching reflows diff --git a/layout/html/base/src/nsScrollPortFrame.cpp b/layout/html/base/src/nsScrollPortFrame.cpp index 0f68eb06ec9..2300909e73f 100644 --- a/layout/html/base/src/nsScrollPortFrame.cpp +++ b/layout/html/base/src/nsScrollPortFrame.cpp @@ -297,6 +297,9 @@ nsScrollPortFrame::GetBorder(nsMargin& aMargin) NS_IMETHODIMP nsScrollPortFrame::Layout(nsBoxLayoutState& aState) { + PRUint32 flags = 0; + aState.GetLayoutFlags(flags); + nsRect clientRect(0,0,0,0); GetClientRect(clientRect); nsIBox* kid = nsnull; @@ -324,8 +327,10 @@ nsScrollPortFrame::Layout(nsBoxLayoutState& aState) if (min.width > childRect.width) childRect.width = min.width; + aState.SetLayoutFlags(NS_FRAME_NO_MOVE_VIEW); kid->SetBounds(aState, childRect); kid->Layout(aState); + kid->GetBounds(childRect); clientRect.Inflate(margin); @@ -343,6 +348,8 @@ nsScrollPortFrame::Layout(nsBoxLayoutState& aState) kid->SetBounds(aState, childRect); } + aState.SetLayoutFlags(flags); + SyncLayout(aState); nsIPresContext* presContext = aState.GetPresContext(); diff --git a/layout/html/forms/src/nsFieldSetFrame.cpp b/layout/html/forms/src/nsFieldSetFrame.cpp index 592d099a5f3..410c5fd12a4 100644 --- a/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/layout/html/forms/src/nsFieldSetFrame.cpp @@ -285,6 +285,9 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, return Reflow(aPresContext, aDesiredSize, newState, aStatus); } break; + + default: + NS_ERROR("Unexpected Reflow Type"); } } else { aReflowState.reflowCommand->GetNext(incrementalChild); diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 1dadbfe38c7..85a78b27f44 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -77,6 +77,7 @@ #include "nsLegendFrame.h" #include "nsTitleFrame.h" #include "nsIContentIterator.h" +#include "nsBoxLayoutState.h" #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" @@ -9043,31 +9044,29 @@ StyleChangeReflow(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIAtom * aAttribute) { - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); + + // Is it a box? If so we can coelesce. + nsresult rv; + nsCOMPtr box = do_QueryInterface(aFrame, &rv); + if (NS_SUCCEEDED(rv) && box) { + nsBoxLayoutState state(aPresContext); + box->MarkStyleChange(state); + } else { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsIReflowCommand* reflowCmd; + nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, + nsIReflowCommand::StyleChanged, + nsnull, + aAttribute); - nsIReflowCommand* reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, - nsIReflowCommand::StyleChanged, - nsnull, - aAttribute); - if (NS_SUCCEEDED(rv)) { - shell->AppendReflowCommand(reflowCmd); - NS_RELEASE(reflowCmd); + if (NS_SUCCEEDED(rv)) { + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } } - - /* - - nsFrameState state; - aFrame->GetFrameState(&state); - state |= NS_FRAME_IS_DIRTY; - aFrame->SetFrameState(state); - nsIFrame* parent; - aFrame->GetParent(&parent); - parent->ReflowDirtyChild(shell, aFrame); -*/ } NS_IMETHODIMP diff --git a/layout/xul/base/src/nsBox.cpp b/layout/xul/base/src/nsBox.cpp index d584f70a95b..b9d41f33494 100644 --- a/layout/xul/base/src/nsBox.cpp +++ b/layout/xul/base/src/nsBox.cpp @@ -44,7 +44,21 @@ #include "nsHTMLAtoms.h" #include "nsXULAtoms.h" -nsBox::nsBox(nsIPresShell* aShell):mParentBox(nsnull),mNextChild(nsnull),mMouseThrough(unset) +#undef DEBUG_evaughan + +#ifdef DEBUG_evaughan +static PRInt32 coelesced = 0; + +void Coelesced() +{ + printf("Coelesed=%d\n", ++coelesced); +} + +#endif + +nsBox::nsBox(nsIPresShell* aShell):mParentBox(nsnull), + mNextChild(nsnull), + mMouseThrough(unset) { //mX = 0; //mY = 0; @@ -64,6 +78,7 @@ nsBox::IsDirty(PRBool& aDirty) nsIFrame* frame; GetFrame(&frame); frame->GetFrameState(&state); + aDirty = (state & NS_FRAME_IS_DIRTY); return NS_OK; } @@ -75,6 +90,7 @@ nsBox::HasDirtyChildren(PRBool& aDirty) nsIFrame* frame; GetFrame(&frame); frame->GetFrameState(&state); + aDirty = (state & NS_FRAME_HAS_DIRTY_CHILDREN); return NS_OK; } @@ -90,8 +106,12 @@ nsBox::MarkDirty(nsBoxLayoutState& aState) frame->GetFrameState(&state); // only reflow if we aren't already dirty. - if (state & NS_FRAME_IS_DIRTY) + if (state & NS_FRAME_IS_DIRTY) { +#ifdef DEBUG_evaughan + Coelesced(); +#endif return NS_OK; + } state |= NS_FRAME_IS_DIRTY; frame->SetFrameState(state); @@ -101,8 +121,12 @@ nsBox::MarkDirty(nsBoxLayoutState& aState) if (layout) layout->BecameDirty(this, aState); - if (state & NS_FRAME_HAS_DIRTY_CHILDREN) + if (state & NS_FRAME_HAS_DIRTY_CHILDREN) { +#ifdef DEBUG_evaughan + Coelesced(); +#endif return NS_OK; + } nsIBox* parent = nsnull; GetParentBox(&parent); @@ -123,6 +147,137 @@ nsBox::MarkDirtyChildren(nsBoxLayoutState& aState) return RelayoutDirtyChild(aState, nsnull); } +NS_IMETHODIMP +nsBox::MarkStyleChange(nsBoxLayoutState& aState) +{ + NeedsRecalc(); + + PRBool dirty = PR_FALSE; + if (HasStyleChange()) + return NS_OK; + + // iterate through all children making them dirty + MarkChildrenStyleChange(); + + nsIBox* parent = nsnull; + GetParentBox(&parent); + if (parent) + return parent->RelayoutDirtyChild(aState, this); + else { + /* + nsCOMPtr shell; + aState.GetPresShell(getter_AddRefs(shell)); + nsIFrame* frame = nsnull; + GetFrame(&frame); + nsFrame::CreateAndPostReflowCommand(shell, frame, + nsIReflowCommand::StyleChange, nsnull, nsnull, nsnull); + return NS_OK; + */ + nsIFrame* frame = nsnull; + GetFrame(&frame); + nsIFrame* parent = nsnull; + frame->GetParent(&parent); + nsCOMPtr shell; + aState.GetPresShell(getter_AddRefs(shell)); + return parent->ReflowDirtyChild(shell, frame); + + } + + return NS_OK; +} + +PRBool +nsBox::HasStyleChange() +{ + PRBool aDirty = PR_FALSE; + IsDirty(aDirty); + return aDirty; +} + +void +nsBox::SetStyleChangeFlag(PRBool aDirty) +{ + NeedsRecalc(); + + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + state |= (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN); + frame->SetFrameState(state); +} + +NS_IMETHODIMP +nsBox::MarkChildrenStyleChange() +{ + // only reflow if we aren't already dirty. + if (HasStyleChange()) { +#ifdef DEBUG_evaughan + printf("StyleChange reflows coelesced=%d\n", ++StyleCoelesced); +#endif + return NS_OK; + } + + SetStyleChangeFlag(PR_TRUE); + + nsIBox* child = nsnull; + GetChildBox(&child); + while(child) + { + child->MarkChildrenStyleChange(); + child->GetNextBox(&child); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsBox::RelayoutStyleChange(nsBoxLayoutState& aState, nsIBox* aChild) +{ + NS_ERROR("Don't call this!!"); + + /* + nsFrameState state; + nsIFrame* frame; + GetFrame(&frame); + frame->GetFrameState(&state); + + // if we are not dirty mark ourselves dirty and tell our parent we are dirty too. + if (!HasStyleChange()) { + // Mark yourself as dirty and needing to be recalculated + SetStyleChangeFlag(PR_TRUE); + NeedsRecalc(); + + if (aChild != nsnull) { + nsCOMPtr layout; + GetLayoutManager(getter_AddRefs(layout)); + if (layout) + layout->ChildBecameDirty(this, aState, aChild); + } + + nsIBox* parent = nsnull; + GetParentBox(&parent); + if (parent) + return parent->RelayoutStyleChange(aState, this); + else { + nsCOMPtr shell; + aState.GetPresShell(getter_AddRefs(shell)); + nsIFrame* frame = nsnull; + aChild->GetFrame(&frame); + nsFrame::CreateAndPostReflowCommand(shell, frame, + nsIReflowCommand::StyleChanged, nsnull, nsnull, nsnull); + return NS_OK; + } + } else { +#ifdef DEBUG_evaughan + Coelesced(); +#endif + } + */ + + return NS_OK; +} + NS_IMETHODIMP nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild) { @@ -156,6 +311,10 @@ nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild) aState.GetPresShell(getter_AddRefs(shell)); return parent->ReflowDirtyChild(shell, frame); } + } else { +#ifdef DEBUG_evaughan + Coelesced(); +#endif } return NS_OK; @@ -220,7 +379,7 @@ nsBox::GetBounds(nsRect& aRect) } NS_IMETHODIMP -nsBox::SetBounds(nsBoxLayoutState& aLayoutState, const nsRect& aRect) +nsBox::SetBounds(nsBoxLayoutState& aState, const nsRect& aRect) { NS_ASSERTION(aRect.width >=0 && aRect.height >= 0, "SetBounds Size < 0"); @@ -230,10 +389,42 @@ nsBox::SetBounds(nsBoxLayoutState& aLayoutState, const nsRect& aRect) nsIFrame* frame = nsnull; GetFrame(&frame); - nsIPresContext* presContext = aLayoutState.GetPresContext(); - frame->SetRect(presContext, aRect); + nsIPresContext* presContext = aState.GetPresContext(); + + PRUint32 flags = 0; + GetLayoutFlags(flags); + + PRUint32 stateFlags = 0; + aState.GetLayoutFlags(stateFlags); + + flags |= stateFlags; + + if (flags & NS_FRAME_NO_MOVE_FRAME) + frame->SizeTo(presContext, aRect.width, aRect.height); + else + frame->SetRect(presContext, aRect); + if (!(flags & NS_FRAME_NO_MOVE_VIEW) || !(flags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) + { + nsIView* view; + frame->GetView(presContext, &view); + if (view) { + if (!(flags & NS_FRAME_NO_MOVE_VIEW)) { + nsContainerFrame::PositionFrameView(presContext, frame, view); + } + } else { + if (!(flags & NS_FRAME_NO_MOVE_CHILD_VIEWS)) { + // only if the origin changed + if ((rect.x != aRect.x) || (rect.y != aRect.y)) { + nsContainerFrame::PositionChildViews(presContext, frame); + } + } + } + } + + + /* // only if the origin changed if ((rect.x != aRect.x) || (rect.y != aRect.y)) { nsIView* view; @@ -244,10 +435,18 @@ nsBox::SetBounds(nsBoxLayoutState& aLayoutState, const nsRect& aRect) nsContainerFrame::PositionChildViews(presContext, frame); } } + */ + return NS_OK; } +void +nsBox::GetLayoutFlags(PRUint32& aFlags) +{ + aFlags = 0; +} + NS_IMETHODIMP nsBox::GetBorderAndPadding(nsMargin& aBorderAndPadding) @@ -256,8 +455,11 @@ nsBox::GetBorderAndPadding(nsMargin& aBorderAndPadding) GetFrame(&frame); const nsStyleSpacing* spacing; - nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, - (const nsStyleStruct*&) spacing); + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + if (NS_FAILED(rv)) + return rv; nsMargin border; nsMargin padding; @@ -267,7 +469,7 @@ nsBox::GetBorderAndPadding(nsMargin& aBorderAndPadding) aBorderAndPadding += border; aBorderAndPadding += padding; - return NS_OK; + return rv; } NS_IMETHODIMP @@ -277,13 +479,16 @@ nsBox::GetBorder(nsMargin& aMargin) GetFrame(&frame); const nsStyleSpacing* spacing; - nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&) spacing); + if (NS_FAILED(rv)) + return rv; + aMargin.SizeTo(0,0,0,0); spacing->GetBorder(aMargin); - return NS_OK; + return rv; } NS_IMETHODIMP @@ -293,13 +498,16 @@ nsBox::GetPadding(nsMargin& aMargin) GetFrame(&frame); const nsStyleSpacing* spacing; - nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, + nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&) spacing); + if (NS_FAILED(rv)) + return rv; + aMargin.SizeTo(0,0,0,0); spacing->GetPadding(aMargin); - return NS_OK; + return rv; } NS_IMETHODIMP @@ -312,10 +520,13 @@ nsBox::GetMargin(nsMargin& aMargin) nsresult rv = frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&) spacing); + if (NS_FAILED(rv)) + return rv; + aMargin.SizeTo(0,0,0,0); spacing->GetMargin(aMargin); - return NS_OK; + return rv; } NS_IMETHODIMP @@ -498,7 +709,6 @@ nsBox::UnCollapse(nsBoxLayoutState& aState) nsresult nsBox::UnCollapseChild(nsBoxLayoutState& aState, nsIBox* aBox) { - nsIPresContext* presContext = aState.GetPresContext(); nsIFrame* frame; aBox->GetFrame(&frame); @@ -581,7 +791,6 @@ nsBox::GetFlex(nsBoxLayoutState& aState, nscoord& aFlex) { aFlex = 0; GetDefaultFlex(aFlex); - PRBool collapsed = PR_FALSE; nsIBox::AddCSSFlex(aState, this, aFlex); return NS_OK; @@ -646,12 +855,21 @@ nsBox::SyncLayout(nsBoxLayoutState& aState) nsIFrame* frame; GetFrame(&frame); frame->GetFrameState(&state); - state &= ~(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY | NS_FRAME_FIRST_REFLOW); + state &= ~(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY | NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW); frame->SetFrameState(state); nsIPresContext* presContext = aState.GetPresContext(); nsRect rect(0,0,0,0); GetBounds(rect); + + PRUint32 flags = 0; + GetLayoutFlags(flags); + + PRUint32 stateFlags = 0; + aState.GetLayoutFlags(stateFlags); + + flags |= stateFlags; + nsIView* view; frame->GetView(presContext, &view); @@ -676,7 +894,7 @@ nsBox::SyncLayout(nsBoxLayoutState& aState) frame, view, nsnull, - NS_FRAME_NO_MOVE_VIEW); + flags); } @@ -741,7 +959,6 @@ nsBox::Redraw(nsBoxLayoutState& aState, PRBool nsIBox::AddCSSPrefSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) { - nsIPresContext* presContext = aState.GetPresContext(); PRBool widthSet = PR_FALSE; PRBool heightSet = PR_FALSE; nsIFrame* frame = nsnull; @@ -767,6 +984,8 @@ nsIBox::AddCSSPrefSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) frame->GetContent(getter_AddRefs(content)); if (content) { + nsIPresContext* presContext = aState.GetPresContext(); + nsAutoString value; PRInt32 error; @@ -800,7 +1019,6 @@ nsIBox::AddCSSPrefSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) PRBool nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) { - nsIPresContext* presContext = aState.GetPresContext(); PRBool widthSet = PR_FALSE; PRBool heightSet = PR_FALSE; @@ -837,7 +1055,6 @@ nsIBox::AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) PRBool nsIBox::AddCSSMaxSize(nsBoxLayoutState& aState, nsIBox* aBox, nsSize& aSize) { - nsIPresContext* presContext = aState.GetPresContext(); PRBool widthSet = PR_FALSE; PRBool heightSet = PR_FALSE; diff --git a/layout/xul/base/src/nsBox.h b/layout/xul/base/src/nsBox.h index f497468a425..833a3709235 100644 --- a/layout/xul/base/src/nsBox.h +++ b/layout/xul/base/src/nsBox.h @@ -74,8 +74,12 @@ public: NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox); NS_IMETHOD GetDebug(PRBool& aDebug); NS_IMETHOD RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild); + NS_IMETHOD RelayoutStyleChange(nsBoxLayoutState& aState, nsIBox* aChild); NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough); + NS_IMETHOD MarkChildrenStyleChange(); + NS_IMETHOD MarkStyleChange(nsBoxLayoutState& aState); + // XXX Eventually these will move into nsIFrame. // These methods are used for XBL . NS_IMETHOD GetInsertionPoint(nsIFrame** aFrame) { return NS_OK; }; @@ -105,9 +109,13 @@ public: static void BoundsCheck(nsSize& aMinSize, nsSize& aPrefSize, nsSize& aMaxSize); protected: + virtual PRBool HasStyleChange(); + virtual void SetStyleChangeFlag(PRBool aDirty); + virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState); virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas); virtual PRBool GetDefaultFlex(PRInt32& aFlex); + virtual void GetLayoutFlags(PRUint32& aFlags); enum eMouseThrough { unset, diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index e2b7e4eec99..c9b05fa33b3 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -75,6 +75,8 @@ #include "nsIBoxLayout.h" #include "nsSprocketLayout.h" +#undef DEBUG_evaughan + #define CONSTANT 0 //#define DEBUG_REFLOW //define DEBUG_REDRAW @@ -623,7 +625,7 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext, nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize); // coelesce reflows if we are root. - state.HandleReflow(this, PR_FALSE); + state.HandleReflow(this); nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight); @@ -1084,6 +1086,33 @@ nsBoxFrame::GetInset(nsMargin& margin) return NS_OK; } +#ifdef DEBUG_evaughan +static PRInt32 StyleCoelesced = 0; +#endif + +PRBool +nsBoxFrame::HasStyleChange() +{ + return mState & NS_STATE_STYLE_CHANGE; +} + +void +nsBoxFrame::SetStyleChangeFlag(PRBool aDirty) +{ + if (aDirty) + mState |= (NS_STATE_STYLE_CHANGE | NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN); + else + mState &= ~NS_STATE_STYLE_CHANGE; +} + +nsresult +nsBoxFrame::SyncLayout(nsBoxLayoutState& aState) +{ + nsresult rv = nsBox::SyncLayout(aState); + mState &= ~(NS_STATE_STYLE_CHANGE); + return rv; +} + NS_IMETHODIMP nsBoxFrame :: Paint ( nsIPresContext* aPresContext, @@ -1157,6 +1186,8 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, nscoord onePixel; nsRect inner; + GetBorder(border); + if (mState & NS_STATE_CURRENTLY_IN_DEBUG) { PRBool isHorizontal = IsHorizontal(); @@ -1176,10 +1207,8 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, GetContentRect(inner); inner.Deflate(debugMargin); - GetBorder(border); - inner.Deflate(border); - nsRect borderRect(inner); + //nsRect borderRect(inner); nscolor color; if (isHorizontal) { @@ -1228,12 +1257,7 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, // don't leak out of us if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { nsMargin im(0,0,0,0); - nsBoxLayoutState state(aPresContext); GetInset(im); - nsMargin border(0,0,0,0); - const nsStyleSpacing* spacing = (const nsStyleSpacing*) - mStyleContext->GetStyleData(eStyleStruct_Spacing); - spacing->GetBorderPadding(border); r.Deflate(im); r.Deflate(border); } @@ -1703,7 +1727,7 @@ nsBoxFrameInner::PaintDebug(nsIBox* aBox, inner.Deflate(debugMargin); - nsRect borderRect(inner); + //nsRect borderRect(inner); nscolor color; if (isHorizontal) { diff --git a/layout/xul/base/src/nsBoxFrame.h b/layout/xul/base/src/nsBoxFrame.h index 218f4dc371a..9794a335db5 100644 --- a/layout/xul/base/src/nsBoxFrame.h +++ b/layout/xul/base/src/nsBoxFrame.h @@ -57,6 +57,7 @@ class nsHTMLInfo; #define NS_STATE_DEBUG_WAS_SET 0x08000000 #define NS_STATE_IS_COLLAPSED 0x10000000 #define NS_STATE_DEFAULT_HORIZONTAL 0x20000000 +#define NS_STATE_STYLE_CHANGE 0x40000000 class nsBoxFrame : public nsHTMLContainerFrame, public nsContainerBox { @@ -90,6 +91,7 @@ public: NS_IMETHOD GetInset(nsMargin& aInset); NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); NS_IMETHOD GetDebug(PRBool& aDebug); + //NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough); // ----- child and sibling operations --- @@ -153,7 +155,6 @@ public: nsIAtom* aListName, nsIFrame* aChildList); - NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD DidReflow(nsIPresContext* aPresContext, @@ -164,14 +165,18 @@ public: virtual ~nsBoxFrame(); virtual nsresult GetContentOf(nsIContent** aContent); + virtual nsresult SyncLayout(nsBoxLayoutState& aBoxLayoutState); nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE); protected: + virtual PRBool HasStyleChange(); + virtual void SetStyleChangeFlag(PRBool aDirty); virtual void PropagateDebug(nsBoxLayoutState& aState); + // Paint one child frame virtual void PaintChild(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, diff --git a/layout/xul/base/src/nsBoxLayoutState.cpp b/layout/xul/base/src/nsBoxLayoutState.cpp index 53428921d36..7ae74fef750 100644 --- a/layout/xul/base/src/nsBoxLayoutState.cpp +++ b/layout/xul/base/src/nsBoxLayoutState.cpp @@ -37,7 +37,13 @@ #include "nsINameSpaceManager.h" #include "nsIPresContext.h" -nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext):mPresContext(aPresContext), mReflowState(nsnull), mMaxElementSize(nsnull) +nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext):mPresContext(aPresContext), + mReflowState(nsnull), + mMaxElementSize(nsnull), + mType(Dirty), + mOverFlowSize(0,0), + mIncludeOverFlow(PR_TRUE), + mLayoutFlags(0) { } @@ -49,12 +55,27 @@ nsBoxLayoutState::nsBoxLayoutState(const nsBoxLayoutState& aState) mMaxElementSize = aState.mMaxElementSize; } -nsBoxLayoutState::nsBoxLayoutState(nsIPresShell* aShell):mReflowState(nsnull), mMaxElementSize(nsnull) +nsBoxLayoutState::nsBoxLayoutState(nsIPresShell* aShell):mReflowState(nsnull), + mType(Dirty), + mMaxElementSize(nsnull), + mOverFlowSize(0,0), + mIncludeOverFlow(PR_TRUE), + mLayoutFlags(0) { aShell->GetPresContext(getter_AddRefs(mPresContext)); } -nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize):mReflowState(&aReflowState),mPresContext(aPresContext),mType(Dirty) +nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext, + const nsHTMLReflowState& aReflowState, + nsHTMLReflowMetrics& aDesiredSize):mReflowState(&aReflowState), + mPresContext(aPresContext), + mType(Dirty), + mIncludeOverFlow(PR_TRUE), + mOverFlowSize(0,0), + mLayoutFlags(0) + + + { mMaxElementSize = aDesiredSize.maxElementSize; } @@ -67,24 +88,54 @@ nsBoxLayoutState::GetMaxElementSize(nsSize** aMaxElementSize) *aMaxElementSize = mMaxElementSize; } +void +nsBoxLayoutState::GetOverFlowSize(nsSize& aSize) +{ + aSize = mOverFlowSize; +} -PRBool -nsBoxLayoutState::HandleReflow(nsIBox* aRootBox, PRBool aCoelesce) +void +nsBoxLayoutState::SetOverFlowSize(const nsSize& aSize) +{ + mOverFlowSize = aSize; +} + +void +nsBoxLayoutState::GetIncludeOverFlow(PRBool& aOverflow) +{ + aOverflow = mIncludeOverFlow; +} + +void +nsBoxLayoutState::SetLayoutFlags(const PRUint32& aFlags) +{ + mLayoutFlags = aFlags; +} + +void +nsBoxLayoutState::GetLayoutFlags(PRUint32& aFlags) +{ + aFlags = mLayoutFlags; +} + +void +nsBoxLayoutState::SetIncludeOverFlow(const PRBool& aOverflow) +{ + mIncludeOverFlow = aOverflow; +} + +void +nsBoxLayoutState::HandleReflow(nsIBox* aRootBox) { switch(mReflowState->reason) { case eReflowReason_Incremental: { - nsIReflowCommand::ReflowType type; - mReflowState->reflowCommand->GetType(type); - // ok if the target was not a box. Then unwind it down - if (UnWind(mReflowState->reflowCommand, aRootBox, aCoelesce)) { - mType = Dirty; - return PR_TRUE; - } - - } // fall into dirty + UnWind(mReflowState->reflowCommand, aRootBox); + mType = Dirty; + break; + } case eReflowReason_Dirty: mType = Dirty; @@ -104,23 +155,20 @@ nsBoxLayoutState::HandleReflow(nsIBox* aRootBox, PRBool aCoelesce) case eReflowReason_StyleChange: printf("STYLE CHANGE REFLOW. Blowing away all box caches!!\n"); - DirtyAllChildren(*this, aRootBox); + aRootBox->MarkChildrenStyleChange(); // fall through to dirty default: mType = Dirty; } - - return PR_FALSE; } -PRBool -nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoelesce) +void +nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox) { // if incremental unwindow the chain nsIFrame* incrementalChild = nsnull; - nsIBox* lastBox = nsnull; nsIFrame* target = nsnull; aCommand->GetTarget(target); nsIReflowCommand::ReflowType type; @@ -130,7 +178,7 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele { aCommand->GetNext(incrementalChild, PR_FALSE); if (incrementalChild == nsnull) - return PR_FALSE; + return; // get the box for the given incrementalChild. If adaptor is true then // it is some wrapped HTML frame. @@ -145,24 +193,22 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele // ok we got a box is it the target? if (incrementalChild == target) { - nsFrameState state; + nsFrameState boxState; nsIFrame* frame; aBox->GetFrame(&frame); - frame->GetFrameState(&state); + frame->GetFrameState(&boxState); - if (aCoelesce) - state &= ~NS_FRAME_HAS_DIRTY_CHILDREN; - else - state |= NS_FRAME_HAS_DIRTY_CHILDREN; + boxState |= NS_FRAME_HAS_DIRTY_CHILDREN; - frame->SetFrameState(state); + frame->SetFrameState(boxState); // the target is a box? // mark it dirty generating a new reflow command targeted // at us and coelesce out this one. - ibox->MarkDirty(*this); if (type == nsIReflowCommand::StyleChanged) { + ibox->MarkStyleChange(*this); + // could be a visiblity change. Like collapse so we need to dirty // parent so it gets redrawn. But be carefull we // don't want to just mark dirty that would notify the @@ -182,11 +228,11 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele parentFrame->SetFrameState(parentState); } - DirtyAllChildren(*this, ibox); - } + } else { + ibox->MarkDirty(*this); + } - // yes we coelesed - return aCoelesce ? PR_TRUE : PR_FALSE; + return; } // was the child html? @@ -209,7 +255,7 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele ibox->MarkDirty(*this); // we are done and we did not coelesce - return PR_FALSE; + return; } } else { @@ -219,8 +265,6 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele aCommand->GetNext(incrementalChild); } - - return PR_FALSE; } /* @@ -312,6 +356,7 @@ nsBoxLayoutState::GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor) return ibox; } +/* void nsBoxLayoutState::DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox) { @@ -328,6 +373,7 @@ nsBoxLayoutState::DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox) first->GetNextBox(&first); } } +*/ void* nsBoxLayoutState::Allocate(size_t sz, nsIPresShell* aPresShell) diff --git a/layout/xul/base/src/nsBoxLayoutState.h b/layout/xul/base/src/nsBoxLayoutState.h index e2e36f50673..1416b433c03 100644 --- a/layout/xul/base/src/nsBoxLayoutState.h +++ b/layout/xul/base/src/nsBoxLayoutState.h @@ -56,12 +56,19 @@ public: nsBoxLayoutState(nsIPresShell* aShell); nsBoxLayoutState(const nsBoxLayoutState& aState); - virtual PRBool HandleReflow(nsIBox* aRootBox, PRBool aCoalesce); + virtual void HandleReflow(nsIBox* aRootBox); virtual nsIPresContext* GetPresContext() { return mPresContext.get(); } virtual nsresult GetPresShell(nsIPresShell** aShell); virtual void GetMaxElementSize(nsSize** aMaxElementSize); + virtual void GetOverFlowSize(nsSize& aSize); + virtual void SetOverFlowSize(const nsSize& aSize); + virtual void GetIncludeOverFlow(PRBool& aOverFlow); + virtual void SetIncludeOverFlow(const PRBool& aOverFlow); + virtual void GetLayoutFlags(PRUint32& aFlags); + virtual void SetLayoutFlags(const PRUint32& aFlags); + virtual eBoxLayoutReason GetLayoutReason() { return mType; } virtual void SetLayoutReason(eBoxLayoutReason aReason) { mType = aReason; } virtual const nsHTMLReflowState* GetReflowState() { return mReflowState; } @@ -75,8 +82,8 @@ public: nsresult AllocateStackMemory(size_t aSize, void** aResult); private: - void DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox); - PRBool UnWind(nsIReflowCommand* aCommand, nsIBox* aRootBox, PRBool aCoalesce); + //void DirtyAllChildren(nsBoxLayoutState& aState, nsIBox* aBox); + void UnWind(nsIReflowCommand* aCommand, nsIBox* aRootBox); nsIBox* GetTargetBox(nsIReflowCommand* mCommand, PRBool& aIsAdaptor); nsIBox* GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor); @@ -84,6 +91,9 @@ private: const nsHTMLReflowState* mReflowState; eBoxLayoutReason mType; nsSize* mMaxElementSize; + nsSize mOverFlowSize; + PRBool mIncludeOverFlow; + PRUint32 mLayoutFlags; }; #endif diff --git a/layout/xul/base/src/nsBoxToBlockAdaptor.cpp b/layout/xul/base/src/nsBoxToBlockAdaptor.cpp index 8d0b3201de6..3c759279910 100644 --- a/layout/xul/base/src/nsBoxToBlockAdaptor.cpp +++ b/layout/xul/base/src/nsBoxToBlockAdaptor.cpp @@ -60,9 +60,24 @@ nsBoxToBlockAdaptor::nsBoxToBlockAdaptor(nsIPresShell* aPresShell, nsIFrame* aFr mSpaceManager = nsnull; mWasCollapsed = PR_FALSE; mCachedMaxElementHeight = 0; + mStyleChange = PR_FALSE; NeedsRecalc(); } +PRBool +nsBoxToBlockAdaptor::HasStyleChange() +{ + return mStyleChange; +} + +void +nsBoxToBlockAdaptor::SetStyleChangeFlag(PRBool aDirty) +{ + nsBox::SetStyleChangeFlag(aDirty); + mStyleChange = PR_TRUE; +} + + void* nsBoxToBlockAdaptor::operator new(size_t sz, nsIPresShell* aPresShell) { @@ -102,14 +117,14 @@ nsBoxToBlockAdaptor::~nsBoxToBlockAdaptor() NS_IMETHODIMP nsBoxToBlockAdaptor::NeedsRecalc() { - nsIBox* parent; + /* nsIBox* parent; GetParentBox(&parent); nsIFrame* frame; if (parent) { parent->GetFrame(&frame); nsFrameState frameState = 0; frame->GetFrameState(&frameState); - } + }*/ mMinWidth = -1; mPrefNeedsRecalc = PR_TRUE; @@ -134,7 +149,6 @@ nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) // see if anything is defined in css. If pref size is competely // defined in css we are golden. We do nothing. But is its not // in css we will have to reflow the child. - nsSize pref(0,0); PRBool completelyRedefined = nsIBox::AddCSSPrefSize(aState, this, mPrefSize); @@ -156,7 +170,8 @@ nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) desiredSize.maxElementSize = &size; } - rv = Reflow(presContext, + rv = Reflow(aState, + presContext, desiredSize, *reflowState, status, @@ -303,7 +318,8 @@ nsBoxToBlockAdaptor::Layout(nsBoxLayoutState& aState) desiredSize.maxElementSize = &size; } - rv = Reflow(presContext, + rv = Reflow(aState, + presContext, desiredSize, *reflowState, status, @@ -334,7 +350,8 @@ nsBoxToBlockAdaptor::Layout(nsBoxLayoutState& aState) } nsresult -nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, +nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, + nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, @@ -392,7 +409,7 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState state(aReflowState); state.reason = eReflowReason_Initial; state.reflowCommand = nsnull; - Reflow(aPresContext, aDesiredSize, state, aStatus, aX, aY, aWidth, aHeight, aMoveFrame); + Reflow(aState, aPresContext, aDesiredSize, state, aStatus, aX, aY, aWidth, aHeight, aMoveFrame); } else { // convert to initial if not incremental. reason = eReflowReason_Initial; @@ -421,14 +438,42 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, // needed in the case just below this one. nsIFrame* incrementalChild = nsnull; aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); - if (incrementalChild == nsnull) - aReflowState.reflowCommand->GetTarget(incrementalChild); + + nsIFrame* targetFrame = nsnull; + aReflowState.reflowCommand->GetTarget(targetFrame); - if (incrementalChild == mFrame) { + if (incrementalChild == mFrame || targetFrame == mFrame) { needsReflow = PR_TRUE; aReflowState.reflowCommand->GetNext(incrementalChild); break; - } + } + + // if incremental but we have already popped off all incremental children + // if (incrementalChild == nsnull) { + // see if its a StyleChange + /* + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + if (type == nsIReflowCommand::StyleChanged) { + if (mStyleChange) { + // if it is and we need a style change reflow then + // reflow. + reason = eReflowReason_StyleChange; + needsReflow = PR_TRUE; + break; + } + } + //} + + + // not us? then just reflow dirty stuff + reason = eReflowReason_Resize; + + // get the frame state to see if it needs reflow + needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); + + break; + */ // fall into dirty } @@ -441,7 +486,7 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, reason = eReflowReason_Resize; // get the frame state to see if it needs reflow - needsReflow = (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); + needsReflow = mStyleChange || (childState & NS_FRAME_IS_DIRTY) || (childState & NS_FRAME_HAS_DIRTY_CHILDREN); } break; @@ -551,6 +596,8 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState reflowState(aPresContext, aReflowState, mFrame, nsSize(size.width, NS_INTRINSICSIZE)); reflowState.reason = reason; + if (reason != eReflowReason_Incremental) + reflowState.reflowCommand = nsnull; if (size.height != NS_INTRINSICSIZE) { size.height -= (border.top + border.bottom); @@ -568,8 +615,6 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, printf(" Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); #endif - // place the child and reflow - mFrame->WillReflow(aPresContext); // if (aMoveFrame) { // PlaceChild(aPresContext, mFrame, aX + margin.left, aY + margin.top); @@ -581,6 +626,35 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, if (reflowState.mComputedHeight == 0) reflowState.mComputedHeight = 1; + + // if we were marked for style change. + // 1) see if we are just supposed to do a resize if so convert to a style change. Kill 2 birds + // with 1 stone. + // 2) If the command is incremental. See if its style change. If it is everything is ok if not + // we need to do a second reflow with the style change. + if (mStyleChange) { + if (reflowState.reason == eReflowReason_Resize) + reflowState.reason = eReflowReason_StyleChange; + else if (reason == eReflowReason_Incremental) { + nsIReflowCommand::ReflowType type; + reflowState.reflowCommand->GetType(type); + + if (type != nsIReflowCommand::StyleChanged) { + mFrame->WillReflow(aPresContext); + mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + mFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + reflowState.mComputedWidth = aDesiredSize.width - (border.left + border.right); + reflowState.availableWidth = reflowState.mComputedWidth; + reflowState.reason = eReflowReason_StyleChange; + reflowState.reflowCommand = nsnull; + } + } + + mStyleChange = PR_FALSE; + } + // place the child and reflow + mFrame->WillReflow(aPresContext); + mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); @@ -615,7 +689,15 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, } */ - if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + // see if the overflow option is set. If it is then if our child's bounds overflow then + // we will set the child's rect to include the overflow size. + + PRBool includeOverFlow = PR_TRUE; + aState.GetIncludeOverFlow(includeOverFlow); + + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + // include the overflow size in our child's rect? + if (includeOverFlow) { //printf("OutsideChildren width=%d, height=%d\n", aDesiredSize.mOverflowArea.width, aDesiredSize.mOverflowArea.height); aDesiredSize.width = aDesiredSize.mOverflowArea.width; if (aDesiredSize.width <= aWidth) @@ -635,6 +717,10 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, aDesiredSize.height = aDesiredSize.mOverflowArea.height; } } + } + + // make sure we store the overflow size + aState.SetOverFlowSize(nsSize(aDesiredSize.mOverflowArea.width, aDesiredSize.mOverflowArea.width)); } @@ -660,7 +746,7 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, nsIRenderingContext& rc = *aReflowState.rendContext; rc.SetFont(font->mFont); nsIFontMetrics* fm; - nsresult rv = rc.GetFontMetrics(fm); + rv = rc.GetFontMetrics(fm); if (NS_SUCCEEDED(rv) && (nsnull != fm)) { fm->GetMaxAscent(aDesiredSize.ascent); NS_RELEASE(fm); diff --git a/layout/xul/base/src/nsBoxToBlockAdaptor.h b/layout/xul/base/src/nsBoxToBlockAdaptor.h index 5a9006269af..b350916f0c1 100644 --- a/layout/xul/base/src/nsBoxToBlockAdaptor.h +++ b/layout/xul/base/src/nsBoxToBlockAdaptor.h @@ -56,10 +56,14 @@ public: virtual ~nsBoxToBlockAdaptor(); protected: + virtual PRBool HasStyleChange(); + virtual void SetStyleChangeFlag(PRBool aDirty); + virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState); virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas); - virtual nsresult Reflow(nsIPresContext* aPresContext, + virtual nsresult Reflow(nsBoxLayoutState& aState, + nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, @@ -83,6 +87,7 @@ protected: nscoord mMinWidth; PRBool mWasCollapsed; nscoord mCachedMaxElementHeight; + PRBool mStyleChange; }; #endif diff --git a/layout/xul/base/src/nsContainerBox.cpp b/layout/xul/base/src/nsContainerBox.cpp index bfe8272ab1c..ee0a2707f49 100644 --- a/layout/xul/base/src/nsContainerBox.cpp +++ b/layout/xul/base/src/nsContainerBox.cpp @@ -416,7 +416,7 @@ nsContainerBox::SanityCheck(nsFrameList& aFrameList) NS_IMETHODIMP -nsContainerBox::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +nsContainerBox::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) { nsresult rv = NS_OK; @@ -424,22 +424,22 @@ nsContainerBox::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) aSize.height = 0; // if the size was not completely redefined in CSS then ask our children - if (!nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize)) + if (!nsIBox::AddCSSPrefSize(aState, this, aSize)) { aSize.width = 0; aSize.height = 0; if (mLayoutManager) { - rv = mLayoutManager->GetPrefSize(this, aBoxLayoutState, aSize); - nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + rv = mLayoutManager->GetPrefSize(this, aState, aSize); + nsIBox::AddCSSPrefSize(aState, this, aSize); } else - rv = nsBox::GetPrefSize(aBoxLayoutState, aSize); + rv = nsBox::GetPrefSize(aState, aSize); } nsSize minSize(0,0); nsSize maxSize(0,0); - GetMinSize(aBoxLayoutState, minSize); - GetMaxSize(aBoxLayoutState, maxSize); + GetMinSize(aState, minSize); + GetMaxSize(aState, maxSize); BoundsCheck(minSize, aSize, maxSize); @@ -447,7 +447,7 @@ nsContainerBox::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) } NS_IMETHODIMP -nsContainerBox::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +nsContainerBox::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) { nsresult rv = NS_OK; @@ -455,16 +455,16 @@ nsContainerBox::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) aSize.height = 0; // if the size was not completely redefined in CSS then ask our children - if (!nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize)) + if (!nsIBox::AddCSSMinSize(aState, this, aSize)) { aSize.width = 0; aSize.height = 0; if (mLayoutManager) { - rv = mLayoutManager->GetMinSize(this, aBoxLayoutState, aSize); - nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); + rv = mLayoutManager->GetMinSize(this, aState, aSize); + nsIBox::AddCSSMinSize(aState, this, aSize); } else { - rv = nsBox::GetMinSize(aBoxLayoutState, aSize); + rv = nsBox::GetMinSize(aState, aSize); } } @@ -472,7 +472,7 @@ nsContainerBox::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) } NS_IMETHODIMP -nsContainerBox::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +nsContainerBox::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize) { nsresult rv = NS_OK; @@ -480,16 +480,16 @@ nsContainerBox::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) aSize.height = NS_INTRINSICSIZE; // if the size was not completely redefined in CSS then ask our children - if (!nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize)) + if (!nsIBox::AddCSSMaxSize(aState, this, aSize)) { aSize.width = NS_INTRINSICSIZE; aSize.height = NS_INTRINSICSIZE; if (mLayoutManager) { - rv = mLayoutManager->GetMaxSize(this, aBoxLayoutState, aSize); - nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize); + rv = mLayoutManager->GetMaxSize(this, aState, aSize); + nsIBox::AddCSSMaxSize(aState, this, aSize); } else { - rv = nsBox::GetMaxSize(aBoxLayoutState, aSize); + rv = nsBox::GetMaxSize(aState, aSize); } } @@ -498,28 +498,33 @@ nsContainerBox::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) NS_IMETHODIMP -nsContainerBox::GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent) +nsContainerBox::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) { nsresult rv = NS_OK; aAscent = 0; if (mLayoutManager) - rv = mLayoutManager->GetAscent(this, aBoxLayoutState, aAscent); + rv = mLayoutManager->GetAscent(this, aState, aAscent); else - rv = nsBox::GetAscent(aBoxLayoutState, aAscent); + rv = nsBox::GetAscent(aState, aAscent); return rv; } NS_IMETHODIMP -nsContainerBox::Layout(nsBoxLayoutState& aBoxLayoutState) +nsContainerBox::Layout(nsBoxLayoutState& aState) { nsresult rv = NS_OK; - if (mLayoutManager) - rv = mLayoutManager->Layout(this, aBoxLayoutState); + PRUint32 oldFlags = 0; + aState.GetLayoutFlags(oldFlags); - nsBox::Layout(aBoxLayoutState); + if (mLayoutManager) + rv = mLayoutManager->Layout(this, aState); + + aState.SetLayoutFlags(oldFlags); + + nsBox::Layout(aState); return rv; } @@ -539,6 +544,19 @@ nsContainerBox::GetLayoutManager(nsIBoxLayout** aLayout) return NS_OK; } +/* +nsresult +nsContainerBox::LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect, PRUint32 aLayoutFlags) +{ + PRUint32 oldFlags = 0; + aState.GetLayoutFlags(oldFlags); + aState.SetLayoutFlags(aLayoutFlags); + nsresult rv = LayoutChildAt(aState, aBox, aRect); + aState.SetLayoutFlags(oldFlags); + return rv; +} +*/ + nsresult nsContainerBox::LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) { diff --git a/layout/xul/base/src/nsContainerBox.h b/layout/xul/base/src/nsContainerBox.h index 74f049b0511..519211bc944 100644 --- a/layout/xul/base/src/nsContainerBox.h +++ b/layout/xul/base/src/nsContainerBox.h @@ -68,9 +68,11 @@ public: NS_IMETHOD GetInsertionPoint(nsIFrame** aFrame); NS_IMETHOD SetInsertionPoint(nsIFrame* aFrame); + virtual ~nsContainerBox() {} protected: virtual nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); + //virtual nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect, PRUint32 aFlags); nsIBox* mFirstChild; nsIBox* mLastChild; diff --git a/layout/xul/base/src/nsDeckFrame.cpp b/layout/xul/base/src/nsDeckFrame.cpp index 6f18ddccbc6..28bf1895b46 100644 --- a/layout/xul/base/src/nsDeckFrame.cpp +++ b/layout/xul/base/src/nsDeckFrame.cpp @@ -94,7 +94,7 @@ nsDeckFrame::AttributeChanged(nsIPresContext* aPresContext, MarkDirty(state); } - return NS_OK; + return rv; } nsIFrame* diff --git a/layout/xul/base/src/nsGrippyFrame.cpp b/layout/xul/base/src/nsGrippyFrame.cpp index b90ca75ccfa..88faa9fe42f 100644 --- a/layout/xul/base/src/nsGrippyFrame.cpp +++ b/layout/xul/base/src/nsGrippyFrame.cpp @@ -71,13 +71,15 @@ NS_NewGrippyFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) } // NS_NewGrippyFrame -nsGrippyFrame::nsGrippyFrame(nsIPresShell* aShell):nsTitledButtonFrame(aShell),mCollapsed(PR_FALSE) +nsGrippyFrame::nsGrippyFrame(nsIPresShell* aShell):nsButtonBoxFrame(aShell),mCollapsed(PR_FALSE) { } void nsGrippyFrame::MouseClicked(nsIPresContext* aPresContext) { + //nsButtonBoxFrame::MouseClicked(aPresContext); + nsIFrame* splitter; nsScrollbarButtonFrame::GetParentWithTag(nsXULAtoms::splitter, this, splitter); if (splitter == nsnull) @@ -96,6 +98,7 @@ nsGrippyFrame::MouseClicked(nsIPresContext* aPresContext) } content->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, a, PR_TRUE); + } /* diff --git a/layout/xul/base/src/nsGrippyFrame.h b/layout/xul/base/src/nsGrippyFrame.h index 44ba84184c7..9609a2368a1 100644 --- a/layout/xul/base/src/nsGrippyFrame.h +++ b/layout/xul/base/src/nsGrippyFrame.h @@ -30,12 +30,12 @@ #ifndef nsGrippyFrame_h___ #define nsGrippyFrame_h___ -#include "nsTitledButtonFrame.h" +#include "nsButtonBoxFrame.h" #include "nsCOMPtr.h" #include "nsIContent.h" -class nsGrippyFrame : public nsTitledButtonFrame +class nsGrippyFrame : public nsButtonBoxFrame { public: diff --git a/layout/xul/base/src/nsIBox.h b/layout/xul/base/src/nsIBox.h index c221ae63a60..83649ab66f6 100644 --- a/layout/xul/base/src/nsIBox.h +++ b/layout/xul/base/src/nsIBox.h @@ -99,7 +99,10 @@ public: NS_IMETHOD NeedsRecalc()=0; NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox)=0; NS_IMETHOD RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)=0; + NS_IMETHOD RelayoutStyleChange(nsBoxLayoutState& aState, nsIBox* aChild)=0; NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough)=0; + NS_IMETHOD MarkChildrenStyleChange()=0; + NS_IMETHOD MarkStyleChange(nsBoxLayoutState& aState)=0; // XXX Eventually these will move into nsIFrame. // These methods are used for XBL . diff --git a/layout/xul/base/src/nsImageBoxFrame.cpp b/layout/xul/base/src/nsImageBoxFrame.cpp index 44da8860799..a7a0f4a6b75 100644 --- a/layout/xul/base/src/nsImageBoxFrame.cpp +++ b/layout/xul/base/src/nsImageBoxFrame.cpp @@ -281,7 +281,6 @@ nsImageBoxFrame::Paint(nsIPresContext* aPresContext, nsresult rv = nsLeafBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - nsRect rect (0,0, mRect.width, mRect.height); PaintImage(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); return rv; diff --git a/layout/xul/base/src/nsLeafBoxFrame.cpp b/layout/xul/base/src/nsLeafBoxFrame.cpp index 17a6c0dabcd..0eb781d6ce7 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -147,7 +147,7 @@ nsLeafBoxFrame::Reflow(nsIPresContext* aPresContext, // create the layout state nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize); - state.HandleReflow(this, PR_FALSE); + state.HandleReflow(this); nsSize computedSize(aReflowState.mComputedWidth,aReflowState.mComputedHeight); diff --git a/layout/xul/base/src/nsMenuFrame.cpp b/layout/xul/base/src/nsMenuFrame.cpp index f4008e22c53..b04a64320e9 100644 --- a/layout/xul/base/src/nsMenuFrame.cpp +++ b/layout/xul/base/src/nsMenuFrame.cpp @@ -682,6 +682,7 @@ nsMenuFrame::Layout(nsBoxLayoutState& aState) nsIFrame* popupChild = mPopupFrames.FirstChild(); if (popupChild) { + nsCOMPtr menulist = do_QueryInterface(mContent); nsIBox* ibox = nsnull; @@ -704,7 +705,7 @@ nsMenuFrame::Layout(nsBoxLayoutState& aState) if (menulist && prefSize.width < contentRect.width) prefSize.width = contentRect.width; - // lay it out + // lay it out but make sure we don't move the view. LayoutChildAt(aState, ibox, nsRect(0,0,prefSize.width, prefSize.height)); } diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index a0363996fcc..edfdb78aacd 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -185,6 +185,12 @@ nsMenuPopupFrame::Init(nsIPresContext* aPresContext, return rv; } +void +nsMenuPopupFrame::GetLayoutFlags(PRUint32& aFlags) +{ + aFlags = NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_MOVE_VIEW | NS_FRAME_NO_MOVE_CHILD_VIEWS; +} + PRBool nsMenuPopupFrame::GetInitialOrientation(PRBool& aIsHorizontal) { diff --git a/layout/xul/base/src/nsMenuPopupFrame.h b/layout/xul/base/src/nsMenuPopupFrame.h index 81ffcd08773..f90b116770c 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.h +++ b/layout/xul/base/src/nsMenuPopupFrame.h @@ -138,6 +138,10 @@ public: protected: + // redefine to tell the box system not to move the + // views. + virtual void GetLayoutFlags(PRUint32& aFlags); + // return true if the alignment is horizontal false if vertical virtual PRBool GetInitialOrientation(PRBool& aIsHorizontal); diff --git a/layout/xul/base/src/nsObeliskLayout.cpp b/layout/xul/base/src/nsObeliskLayout.cpp index d52da8c1981..0e8a7477fd3 100644 --- a/layout/xul/base/src/nsObeliskLayout.cpp +++ b/layout/xul/base/src/nsObeliskLayout.cpp @@ -149,7 +149,7 @@ nsObeliskLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSiz // node = node->GetNext(); } - return NS_OK; + return rv; } NS_IMETHODIMP @@ -182,7 +182,7 @@ nsObeliskLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState, nsSize& aSiz // node = node->GetNext(); } - return NS_OK; + return rv; } NS_IMETHODIMP diff --git a/layout/xul/base/src/nsPopupSetFrame.h b/layout/xul/base/src/nsPopupSetFrame.h index c057bdc7bc0..15809b109e1 100644 --- a/layout/xul/base/src/nsPopupSetFrame.h +++ b/layout/xul/base/src/nsPopupSetFrame.h @@ -116,6 +116,7 @@ public: protected: + void MarkAsGenerated(nsIContent* aPopupContent); void UpdateDismissalListener(nsIMenuParent* aMenuParent); diff --git a/layout/xul/base/src/nsSliderFrame.cpp b/layout/xul/base/src/nsSliderFrame.cpp index ac6bdc161a6..1a03e31f573 100644 --- a/layout/xul/base/src/nsSliderFrame.cpp +++ b/layout/xul/base/src/nsSliderFrame.cpp @@ -244,15 +244,15 @@ nsSliderFrame::Paint(nsIPresContext* aPresContext, } NS_IMETHODIMP -nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) +nsSliderFrame::Layout(nsBoxLayoutState& aState) { EnsureOrient(); if (mState & NS_STATE_DEBUG_WAS_SET) { if (mState & NS_STATE_SET_TO_DEBUG) - SetDebug(aBoxLayoutState, PR_TRUE); + SetDebug(aState, PR_TRUE); else - SetDebug(aBoxLayoutState, PR_FALSE); + SetDebug(aState, PR_FALSE); } // get the content area inside our borders @@ -273,7 +273,7 @@ nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) // get the thumb's pref size nsSize thumbSize(0,0); - thumbBox->GetPrefSize(aBoxLayoutState, thumbSize); + thumbBox->GetPrefSize(aState, thumbSize); if (isHorizontal) thumbSize.height = clientRect.height; @@ -290,7 +290,7 @@ nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) curpospx = maxpospx; float p2t; - aBoxLayoutState.GetPresContext()->GetScaledPixelsToTwips(&p2t); + aState.GetPresContext()->GetScaledPixelsToTwips(&p2t); nscoord onePixel = NSIntPixelsToTwips(1, p2t); /* @@ -331,7 +331,7 @@ nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) if (thumbsize > thumbcoord) { nscoord flex = 0; - thumbBox->GetFlex(aBoxLayoutState, flex); + thumbBox->GetFlex(aState, flex); // if the thumb is flexible make the thumb bigger. if (flex > 0) { @@ -356,10 +356,9 @@ nsSliderFrame::Layout(nsBoxLayoutState& aBoxLayoutState) else thumbRect.y += pos; - thumbBox->SetBounds(aBoxLayoutState, thumbRect); - thumbBox->Layout(aBoxLayoutState); - - SyncLayout(aBoxLayoutState); + LayoutChildAt(aState, thumbBox, thumbRect); + + SyncLayout(aState); if (DEBUG_SLIDER) { PRInt32 c = GetCurrentPosition(scrollbar); @@ -500,7 +499,6 @@ nsSliderFrame::GetContentOf(nsIBox* aBox, nsIContent** aContent) { nsIFrame* frame = nsnull; aBox->GetFrame(&frame); - nsIContent* content = nsnull; frame->GetContent(aContent); } diff --git a/layout/xul/base/src/nsSplitterFrame.cpp b/layout/xul/base/src/nsSplitterFrame.cpp index 6438572a49d..cc009387683 100644 --- a/layout/xul/base/src/nsSplitterFrame.cpp +++ b/layout/xul/base/src/nsSplitterFrame.cpp @@ -1093,9 +1093,7 @@ nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInf for (int i=0; i < aCount; i++) { nscoord pref = aChildInfos[i].changed; - nscoord current = aChildInfos[i].current; nsIBox* childBox = aChildInfos[i].child; - PRInt32 index = aChildInfos[i].index; SetPreferredSize(state, childBox, onePixel, aIsHorizontal, &pref); } diff --git a/layout/xul/base/src/nsSprocketLayout.cpp b/layout/xul/base/src/nsSprocketLayout.cpp index 3d690c7c2ed..c8c1db4ccfe 100644 --- a/layout/xul/base/src/nsSprocketLayout.cpp +++ b/layout/xul/base/src/nsSprocketLayout.cpp @@ -124,15 +124,15 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState) PRInt32 flexes = 0; PopulateBoxSizes(aBox, aState, boxSizes, computedBoxSizes, minSize, maxSize, flexes); - nscoord width = clientRect.width; + nscoord size = clientRect.width; if (!IsHorizontal(aBox)) - width = clientRect.height; + size = clientRect.height; - ComputeChildSizes(aBox, aState, width, boxSizes, computedBoxSizes); + ComputeChildSizes(aBox, aState, size, boxSizes, computedBoxSizes); if (IsHorizontal(aBox)) { - clientRect.width = width; + clientRect.width = size; if (clientRect.height < minSize) clientRect.height = minSize; @@ -141,7 +141,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState) clientRect.height = maxSize; } } else { - clientRect.height = width; + clientRect.height = size; if (clientRect.width < minSize) clientRect.width = minSize; diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 9e0bce21237..b01e401c441 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -853,7 +853,9 @@ NS_IMETHODIMP nsView :: SynchWidgetSizePosition() dx->GetAppUnitsToDevUnits(t2p); NS_RELEASE(dx); - + /* You would think that doing a move and resize all in one operation would + * be faster but its not. Something is really broken here. So I'm comenting + * this out for now // if we moved and resized do it all in one shot if (mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED && mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED) { @@ -863,35 +865,63 @@ NS_IMETHODIMP nsView :: SynchWidgetSizePosition() GetOffsetFromWidget(&parx, &pary, pwidget); NS_IF_RELEASE(pwidget); - mWindow->Resize(NSTwipsToIntPixels(mBounds.x + parx, t2p), - NSTwipsToIntPixels(mBounds.y + pary, t2p), - NSTwipsToIntPixels(mBounds.width, t2p), NSTwipsToIntPixels(mBounds.height, t2p), - PR_TRUE); + PRInt32 x = NSTwipsToIntPixels(mBounds.x + parx, t2p); + PRInt32 y = NSTwipsToIntPixels(mBounds.y + pary, t2p); + PRInt32 width = NSTwipsToIntPixels(mBounds.width, t2p); + PRInt32 height = NSTwipsToIntPixels(mBounds.height, t2p); + + nsRect bounds; + mWindow->GetBounds(bounds); + if (bounds.x == x && bounds.y == y ) + mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED; + else if (bounds.width == width && bounds.height == bounds.height) + mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED; + else { + mWindow->Resize(x,y,width,height, PR_TRUE); + mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED; + mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED; + return NS_OK; + } + } + */ + + // if we just resized do it + if (mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED) + { + + PRInt32 width = NSTwipsToIntPixels(mBounds.width, t2p); + PRInt32 height = NSTwipsToIntPixels(mBounds.height, t2p); + + nsRect bounds; + mWindow->GetBounds(bounds); + + if (bounds.width != width || bounds.height != bounds.height) + mWindow->Resize(width,height, PR_TRUE); mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED; + } + + if (mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED) { + // if we just moved do it. + nscoord parx = 0, pary = 0; + nsIWidget *pwidget = nsnull; + + GetOffsetFromWidget(&parx, &pary, pwidget); + NS_IF_RELEASE(pwidget); + + PRInt32 x = NSTwipsToIntPixels(mBounds.x + parx, t2p); + PRInt32 y = NSTwipsToIntPixels(mBounds.y + pary, t2p); + + nsRect bounds; + mWindow->GetBounds(bounds); + + if (bounds.x != x || bounds.y != y) + mWindow->Move(x,y); + mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED; - } else { - // if we just resized do it - if (mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED) - { - mWindow->Resize(NSTwipsToIntPixels(mBounds.width, t2p), NSTwipsToIntPixels(mBounds.height, t2p), - PR_TRUE); - mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_RESIZED; - } else if (mVFlags & NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED) { - // if we just moved do it. - nscoord parx = 0, pary = 0; - nsIWidget *pwidget = nsnull; - - GetOffsetFromWidget(&parx, &pary, pwidget); - NS_IF_RELEASE(pwidget); - - mWindow->Move(NSTwipsToIntPixels(mBounds.x + parx, t2p), - NSTwipsToIntPixels(mBounds.y + pary, t2p)); - - mVFlags &= ~NS_VIEW_PUBLIC_FLAG_WIDGET_MOVED; - } - } + } } + return NS_OK; }