diff --git a/mozilla/layout/base/public/nsIScrollableFrame.h b/mozilla/layout/base/public/nsIScrollableFrame.h index 505d6206e8f..a40c3790ce7 100644 --- a/mozilla/layout/base/public/nsIScrollableFrame.h +++ b/mozilla/layout/base/public/nsIScrollableFrame.h @@ -25,6 +25,7 @@ #include "nsISupports.h" #include "nsCoord.h" +#include "nsIViewManager.h" class nsIFrame; class nsIPresContext; @@ -34,9 +35,17 @@ class nsIPresContext; { 0xc95f1831, 0xc372, 0x11d1, \ { 0xb7, 0x21, 0x0, 0x64, 0x9, 0x92, 0xd8, 0xc9 } } - class nsIScrollableFrame : public nsISupports { public: + + typedef enum { + Auto = 0, + NeverScroll, + AlwaysScroll, + AlwaysScrollVertical, + AlwaysScrollHorizontal + } nsScrollPref; + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLE_FRAME_IID) /** @@ -66,6 +75,38 @@ public: PRBool *aVerticalVisible, PRBool *aHorizontalVisible) const = 0; + /** + * Query whether scroll bars should be displayed all the time, never or + * only when necessary. + * @return current scrollbar selection + */ + NS_IMETHOD GetScrollPreference(nsScrollPref* aScrollPreference) const = 0; + + /** + * Gets the size of the area that lies inside the scrollbars but clips the scrolled frame + */ + NS_IMETHOD GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const = 0; + + + /** + * Get the position of the scrolled view. + */ + NS_IMETHOD GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const=0; + + /** + * Scroll the view to the given x,y, update's the scrollbar's thumb + * positions and the view's offset. Clamps the values to be + * legal. Updates the display based on aUpdateFlags. + * @param aX left edge to scroll to + * @param aY top edge to scroll to + * @param aUpdateFlags passed onto nsIViewManager->UpdateView() + * @return error status + */ + NS_IMETHOD ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags = NS_VMREFRESH_NO_SYNC)=0; + + /** * Set information about whether the vertical and horizontal scrollbars * are currently visible diff --git a/mozilla/layout/forms/nsFieldSetFrame.cpp b/mozilla/layout/forms/nsFieldSetFrame.cpp index 410c5fd12a4..4c3942391ea 100644 --- a/mozilla/layout/forms/nsFieldSetFrame.cpp +++ b/mozilla/layout/forms/nsFieldSetFrame.cpp @@ -70,6 +70,24 @@ public: const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + NS_IMETHOD ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame); #ifdef DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const { return MakeFrameName("FieldSet", aResult); @@ -553,3 +571,57 @@ nsFieldSetFrame::GetSkipSides() const return 0; } +NS_IMETHODIMP +nsFieldSetFrame::AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) +{ + return mContentFrame->AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); +} + +NS_IMETHODIMP +nsFieldSetFrame::InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + return mContentFrame->InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); +} + +NS_IMETHODIMP +nsFieldSetFrame::RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + return mContentFrame->RemoveFrame (aPresContext, + aPresShell, + aListName, + aOldFrame); +} + + +NS_IMETHODIMP +nsFieldSetFrame::ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame) +{ + return mContentFrame->ReplaceFrame (aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); +} + + diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index cfee685251d..71b00bdd12f 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -141,17 +141,23 @@ public: nsresult Layout(nsBoxLayoutState& aState); nsresult LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); - void AddRemoveScrollbar (PRBool& aHasScrollbar, + PRBool AddRemoveScrollbar (PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aOnRightOrBottom, PRBool aAdd); - void AddHorizontalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnBottom); - void AddVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight); - void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnBottom); - void RemoveVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight); + PRBool AddRemoveScrollbar(nsBoxLayoutState& aState, + nsRect& aScrollAreaSize, + PRBool aOnTop, + PRBool aHorizontal, + PRBool aAdd); + + PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); + PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); + PRBool RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); + PRBool RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); @@ -159,6 +165,8 @@ public: void ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY); + void SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible); + nsIBox* mHScrollbarBox; nsIBox* mVScrollbarBox; nsIBox* mScrollAreaBox; @@ -271,6 +279,79 @@ nsGfxScrollFrame::GetScrollbarVisibility(nsIPresContext* aPresContext, } +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const +{ + nsIScrollableView* s = mInner->GetScrollableView(aContext); + return s->GetScrollPosition(aX, aY); +} + +NS_IMETHODIMP +nsGfxScrollFrame::ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags) +{ + nsIScrollableView* s = mInner->GetScrollableView(aContext); + return s->ScrollTo(aX, aY, aFlags); +} + +/** + * Query whether scroll bars should be displayed all the time, never or + * only when necessary. + * @return current scrollbar selection + */ +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollPreference(nsScrollPref* aScrollPreference) const +{ + const nsStyleDisplay* styleDisplay = nsnull; + + GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + switch (styleDisplay->mOverflow) + { + case NS_STYLE_OVERFLOW_SCROLL: + *aScrollPreference = AlwaysScroll; + break; + + case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: + *aScrollPreference = AlwaysScrollHorizontal; + break; + + case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: + *aScrollPreference = AlwaysScrollVertical; + break; + + case NS_STYLE_OVERFLOW_AUTO: + *aScrollPreference = Auto; + break; + + default: + *aScrollPreference = NeverScroll; + } + + return NS_OK; +} + +/** +* Gets the size of the area that lies inside the scrollbars but clips the scrolled frame +*/ +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const +{ + nsBoxLayoutState state(aPresContext); + + nsSize hs; + mInner->mHScrollbarBox->GetPrefSize(state, hs); + *aHbarHeight = hs.height; + + nsSize vs; + mInner->mVScrollbarBox->GetPrefSize(state, vs); + *aVbarWidth = vs.width; + + return NS_OK; +} + NS_IMETHODIMP nsGfxScrollFrame::SetScrollbarVisibility(nsIPresContext* aPresContext, PRBool aVerticalVisible, @@ -309,6 +390,10 @@ nsGfxScrollFrame::CreateAnonymousContent(nsIPresContext* aPresContext, elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content)); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, NS_ConvertToString("horizontal"), PR_FALSE); + + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + NS_ConvertToString("true"), PR_FALSE); + aAnonymousChildren.AppendElement(content); // create vertical scrollbar @@ -316,6 +401,10 @@ nsGfxScrollFrame::CreateAnonymousContent(nsIPresContext* aPresContext, elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content)); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, NS_ConvertToString("vertical"), PR_FALSE); + + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + NS_ConvertToString("true"), PR_FALSE); + aAnonymousChildren.AppendElement(content); // XXX For GFX never have scrollbars @@ -368,37 +457,74 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, return rv; } + NS_IMETHODIMP nsGfxScrollFrame::AppendFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aFrameList) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) { - // Only one child frame allowed - return NS_ERROR_FAILURE; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + return frame->AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); } NS_IMETHODIMP nsGfxScrollFrame::InsertFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsIFrame* aFrameList) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) { - // Only one child frame allowed - return NS_ERROR_FAILURE; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); } NS_IMETHODIMP nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aOldFrame) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) { - // Scroll frame doesn't support incremental changes - return NS_ERROR_NOT_IMPLEMENTED; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->RemoveFrame (aPresContext, + aPresShell, + aListName, + aOldFrame); } + +NS_IMETHODIMP +nsGfxScrollFrame::ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame) +{ + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->ReplaceFrame (aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); +} + + + + NS_IMETHODIMP nsGfxScrollFrame::GetPadding(nsMargin& aMargin) { @@ -449,6 +575,22 @@ nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +NS_IMETHODIMP +nsGfxScrollFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) +{ + aAscent = 0; + nsresult rv = mInner->mScrollAreaBox->GetAscent(aState, aAscent); + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + aAscent += m.top; + GetMargin(m); + aAscent += m.top; + GetInset(m); + aAscent += m.top; + + return rv; +} + NS_IMETHODIMP nsGfxScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) @@ -506,8 +648,7 @@ nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) nsresult rv = mInner->mScrollAreaBox->GetMinSize(aState, aSize); - if (mInner->mHasVerticalScrollbar || - styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { nsSize vSize(0,0); mInner->mVScrollbarBox->GetMinSize(aState, vSize); @@ -517,8 +658,7 @@ nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) aSize.height = vSize.height; } - if (mInner->mHasHorizontalScrollbar || - styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { nsSize hSize(0,0); mInner->mHScrollbarBox->GetMinSize(aState, hSize); @@ -580,7 +720,8 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, size->height = mInner->mMaxElementSize.height; else mInner->mMaxElementSize.height = size->height; - + + // make sure we add in our scrollbar. nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize); @@ -765,18 +906,83 @@ nsGfxScrollFrameInner::GetScrolledContentSize(nsSize& aSize) nsBox::AddInset(mScrollAreaBox, aSize); } -void -nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aRightOrBottom, PRBool aAdd) +PRBool +nsGfxScrollFrameInner::AddHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop) { - if ((aAdd && aHasScrollbar) || (!aAdd && !aHasScrollbar)) - return; - + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_TRUE); +} + +PRBool +nsGfxScrollFrameInner::AddVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE); +} + +PRBool +nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE); +} + +PRBool +nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE); +} + +PRBool +nsGfxScrollFrameInner::AddRemoveScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop, PRBool aHorizontal, PRBool aAdd) +{ + if (aHorizontal) { + if (mNeverHasHorizontalScrollbar) + return PR_FALSE; + + if (aAdd) + SetScrollbarVisibility(mHScrollbarBox, aAdd); + + nsSize hSize; + mHScrollbarBox->GetPrefSize(aState, hSize); + nsBox::AddMargin(mHScrollbarBox, hSize); + + if (!aAdd) + SetScrollbarVisibility(mHScrollbarBox, aAdd); + + PRBool fit = AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, hSize.height, aOnTop, aAdd); + if (!fit) + SetScrollbarVisibility(mHScrollbarBox, !aAdd); + + return fit; + } else { + if (mNeverHasVerticalScrollbar) + return PR_FALSE; + + if (aAdd) + SetScrollbarVisibility(mVScrollbarBox, aAdd); + + nsSize vSize; + mVScrollbarBox->GetPrefSize(aState, vSize); + + if (!aAdd) + SetScrollbarVisibility(mVScrollbarBox, aAdd); + + nsBox::AddMargin(mVScrollbarBox, vSize); + PRBool fit = AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, vSize.width, aOnTop, aAdd); + if (!fit) + SetScrollbarVisibility(mVScrollbarBox, !aAdd); + + return fit; + } +} + +PRBool +nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aRightOrBottom, PRBool aAdd) +{ nscoord size = aSize; if (size != NS_INTRINSICSIZE) { if (aAdd) { size -= aSbSize; - if (!aRightOrBottom) + if (!aRightOrBottom && size >= 0) aXY += aSbSize; } else { size += aSbSize; @@ -785,40 +991,16 @@ nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, n } } - // not enough room? If not don't do anything. + // not enough room? Yes? Return true. if (size >= aSbSize) { aHasScrollbar = aAdd; aSize = size; + return PR_TRUE; } -} -void -nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnTop) -{ - if (!mNeverHasHorizontalScrollbar) - AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, aSbSize.height, aOnTop, PR_TRUE); + return PR_FALSE; } -void -nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight) -{ - if (!mNeverHasVerticalScrollbar) - AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, aSbSize.width, aOnRight, PR_TRUE); -} - -void -nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnTop) -{ - AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, aSbSize.height, aOnTop, PR_FALSE); -} - -void -nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight) -{ - AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, aSbSize.width, aOnRight, PR_FALSE); -} - - nsresult nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) { @@ -828,6 +1010,10 @@ nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const n NS_IMETHODIMP nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) { + // mark ourselves as dirty so no child under us + // can post an incremental layout. + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; + PropagateDebug(aState); PRUint32 flags = 0; aState.GetLayoutFlags(flags); @@ -866,13 +1052,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsRect clientRect(0,0,0,0); mOuter->GetClientRect(clientRect); + // get the preferred size of the scrollbars nsSize hSize(0,0); nsSize vSize(0,0); - mHScrollbarBox->GetPrefSize(aState, hSize); - mVScrollbarBox->GetPrefSize(aState, vSize); nsSize hMinSize(0,0); nsSize vMinSize(0,0); + + /* + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); mHScrollbarBox->GetMinSize(aState, hMinSize); mVScrollbarBox->GetMinSize(aState, vMinSize); @@ -880,44 +1069,24 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBox::AddMargin(mVScrollbarBox, vSize); nsBox::AddMargin(mHScrollbarBox, hMinSize); nsBox::AddMargin(mVScrollbarBox, vMinSize); + */ // the scroll area size starts off as big as our content area nsRect scrollAreaRect(clientRect); - nsSize sbSize(vSize.width, hSize.height); - // Look at our style do we always have vertical or horizontal scrollbars? if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) mHasHorizontalScrollbar = PR_TRUE; if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) mHasVerticalScrollbar = PR_TRUE; - // see if we currenly have a vertical or horizotal scrollbar and subtract them - // from the scroll area size. - if (mHasHorizontalScrollbar) { - if (scrollAreaRect.height - sbSize.height < 0) - { - mHasHorizontalScrollbar = PR_FALSE; - mHScrollbarBox->Collapse(aState); - } else { - scrollAreaRect.height -= sbSize.height; - if (!scrollBarBottom) - scrollAreaRect.y += sbSize.height; - } - } + if (mHasHorizontalScrollbar) + AddHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom); - if (mHasVerticalScrollbar) { - if (scrollAreaRect.width - sbSize.width < 0) - { - mHasVerticalScrollbar = PR_FALSE; - mVScrollbarBox->Collapse(aState); - } else { - scrollAreaRect.width -= sbSize.width; - if (!scrollBarRight) - scrollAreaRect.x += sbSize.width; + if (mHasVerticalScrollbar) + AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight); + - } - } // layout our the scroll area LayoutBox(aState, mScrollAreaBox, scrollAreaRect); @@ -939,19 +1108,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) if (mHasVerticalScrollbar) { // We left room for the vertical scrollbar, but it's not needed; // remove it. - RemoveVerticalScrollbar(sbSize, scrollAreaRect, scrollBarRight); - needsLayout = PR_TRUE; - mVScrollbarBox->Collapse(aState); + if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) + needsLayout = PR_TRUE; } } else { if (!mHasVerticalScrollbar) { // We didn't leave room for the vertical scrollbar, but it turns // out we needed it - if (scrollAreaRect.width - sbSize.width >= 0) { - AddVerticalScrollbar(sbSize, scrollAreaRect, scrollBarRight); - mVScrollbarBox->UnCollapse(aState); + if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) needsLayout = PR_TRUE; - } + } } @@ -960,10 +1126,10 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBoxLayoutState resizeState(aState); resizeState.SetLayoutReason(nsBoxLayoutState::Resize); LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; } } - needsLayout = PR_FALSE; // if scrollbars are auto look at the horizontal case if ((NS_STYLE_OVERFLOW_SCROLL != styleDisplay->mOverflow) @@ -979,11 +1145,10 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { if (!mHasHorizontalScrollbar) { - if (scrollAreaRect.height - sbSize.height >= 0) { - AddHorizontalScrollbar(sbSize, scrollAreaRect, scrollBarBottom); - mHScrollbarBox->UnCollapse(aState); + // no scrollbar? + if (AddHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) needsLayout = PR_TRUE; - } + // if we added a horizonal scrollbar and we did not have a vertical // there is a chance that by adding the horizonal scrollbar we will // suddenly need a vertical scrollbar. Is a special case but its @@ -996,9 +1161,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) // if the area is smaller or equal to and we have a scrollbar then // remove it. if (mHasHorizontalScrollbar) { - RemoveHorizontalScrollbar(sbSize, scrollAreaRect, scrollBarBottom); - mHScrollbarBox->Collapse(aState); - needsLayout = PR_TRUE; + if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) + needsLayout = PR_TRUE; } } } @@ -1008,6 +1172,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBoxLayoutState resizeState(aState); resizeState.SetLayoutReason(nsBoxLayoutState::Resize); LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; } GetScrolledContentSize(scrolledContentSize); @@ -1030,6 +1195,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsIScrollableView* scrollable = GetScrollableView(presContext); scrollable->SetLineHeight(fontHeight); + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); // layout vertical scrollbar nsRect vRect(clientRect); @@ -1054,10 +1221,15 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) } LayoutBox(aState, mVScrollbarBox, vRect); + mVScrollbarBox->GetPrefSize(aState, vSize); + mVScrollbarBox->GetMinSize(aState, vMinSize); - if (!mHasVerticalScrollbar || (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) - mVScrollbarBox->Collapse(aState); + if (mHasVerticalScrollbar && (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) { + if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) + needsLayout = PR_TRUE; + mVScrollbarBox->GetPrefSize(aState, vSize); + } // layout horizontal scrollbar nsRect hRect(clientRect); @@ -1083,10 +1255,23 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) } LayoutBox(aState, mHScrollbarBox, hRect); - - if (!mHasHorizontalScrollbar || (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { - mHScrollbarBox->Collapse(aState); + + mHScrollbarBox->GetMinSize(aState, hMinSize); + + if (mHasHorizontalScrollbar && (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { + if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) + needsLayout = PR_TRUE; } + + // we only need to set the rect. The inner child stays the same size. + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; + } + + return NS_OK; } @@ -1135,6 +1320,31 @@ nsGfxScrollFrameInner::SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, return PR_FALSE; } +void +nsGfxScrollFrameInner::SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible) +{ + nsIFrame* frame = nsnull; + aScrollbar->GetFrame(&frame); + + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + + PRBool old = PR_TRUE; + + nsAutoString value; + + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, value)) + old = PR_FALSE; + + if (aVisible == old) + return; + + if (!aVisible) + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, NS_ConvertToString("true"), PR_TRUE); + else + content->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, PR_TRUE); +} + PRInt32 nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32 defaultValue) { diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index 48379349374..6b6d5f9341a 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -79,6 +79,12 @@ public: nsIFrame* aPrevFrame, nsIFrame* aFrameList); + NS_IMETHOD ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame); + NS_IMETHOD Destroy(nsIPresContext* aPresContext); // This function returns NS_ERROR_NOT_IMPLEMENTED @@ -113,6 +119,8 @@ public: NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); NS_IMETHOD GetPadding(nsMargin& aPadding); @@ -122,12 +130,23 @@ public: NS_IMETHOD GetScrollbarVisibility(nsIPresContext* aPresContext, PRBool *aVerticalVisible, PRBool *aHorizontalVisible) const; + + NS_IMETHOD GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const; + NS_IMETHOD ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags); + NS_IMETHOD SetScrollbarVisibility(nsIPresContext* aPresContext, PRBool aVerticalVisible, PRBool aHorizontalVisible); NS_IMETHOD GetClipSize(nsIPresContext* aPresContext, nscoord *aWidth, nscoord *aHeight) const; + + NS_IMETHOD GetScrollPreference(nsScrollPref* aScrollPreference) const; + + NS_IMETHOD GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const; + /** * Get the "type" of the frame * diff --git a/mozilla/layout/generic/nsIScrollableFrame.h b/mozilla/layout/generic/nsIScrollableFrame.h index 505d6206e8f..a40c3790ce7 100644 --- a/mozilla/layout/generic/nsIScrollableFrame.h +++ b/mozilla/layout/generic/nsIScrollableFrame.h @@ -25,6 +25,7 @@ #include "nsISupports.h" #include "nsCoord.h" +#include "nsIViewManager.h" class nsIFrame; class nsIPresContext; @@ -34,9 +35,17 @@ class nsIPresContext; { 0xc95f1831, 0xc372, 0x11d1, \ { 0xb7, 0x21, 0x0, 0x64, 0x9, 0x92, 0xd8, 0xc9 } } - class nsIScrollableFrame : public nsISupports { public: + + typedef enum { + Auto = 0, + NeverScroll, + AlwaysScroll, + AlwaysScrollVertical, + AlwaysScrollHorizontal + } nsScrollPref; + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLE_FRAME_IID) /** @@ -66,6 +75,38 @@ public: PRBool *aVerticalVisible, PRBool *aHorizontalVisible) const = 0; + /** + * Query whether scroll bars should be displayed all the time, never or + * only when necessary. + * @return current scrollbar selection + */ + NS_IMETHOD GetScrollPreference(nsScrollPref* aScrollPreference) const = 0; + + /** + * Gets the size of the area that lies inside the scrollbars but clips the scrolled frame + */ + NS_IMETHOD GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const = 0; + + + /** + * Get the position of the scrolled view. + */ + NS_IMETHOD GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const=0; + + /** + * Scroll the view to the given x,y, update's the scrollbar's thumb + * positions and the view's offset. Clamps the values to be + * legal. Updates the display based on aUpdateFlags. + * @param aX left edge to scroll to + * @param aY top edge to scroll to + * @param aUpdateFlags passed onto nsIViewManager->UpdateView() + * @return error status + */ + NS_IMETHOD ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags = NS_VMREFRESH_NO_SYNC)=0; + + /** * Set information about whether the vertical and horizontal scrollbars * are currently visible diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index cfee685251d..71b00bdd12f 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -141,17 +141,23 @@ public: nsresult Layout(nsBoxLayoutState& aState); nsresult LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); - void AddRemoveScrollbar (PRBool& aHasScrollbar, + PRBool AddRemoveScrollbar (PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aOnRightOrBottom, PRBool aAdd); - void AddHorizontalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnBottom); - void AddVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight); - void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnBottom); - void RemoveVerticalScrollbar (const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight); + PRBool AddRemoveScrollbar(nsBoxLayoutState& aState, + nsRect& aScrollAreaSize, + PRBool aOnTop, + PRBool aHorizontal, + PRBool aAdd); + + PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); + PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); + PRBool RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); + PRBool RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); @@ -159,6 +165,8 @@ public: void ScrollbarChanged(nsIPresContext* aPresContext, nscoord aX, nscoord aY); + void SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible); + nsIBox* mHScrollbarBox; nsIBox* mVScrollbarBox; nsIBox* mScrollAreaBox; @@ -271,6 +279,79 @@ nsGfxScrollFrame::GetScrollbarVisibility(nsIPresContext* aPresContext, } +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const +{ + nsIScrollableView* s = mInner->GetScrollableView(aContext); + return s->GetScrollPosition(aX, aY); +} + +NS_IMETHODIMP +nsGfxScrollFrame::ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags) +{ + nsIScrollableView* s = mInner->GetScrollableView(aContext); + return s->ScrollTo(aX, aY, aFlags); +} + +/** + * Query whether scroll bars should be displayed all the time, never or + * only when necessary. + * @return current scrollbar selection + */ +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollPreference(nsScrollPref* aScrollPreference) const +{ + const nsStyleDisplay* styleDisplay = nsnull; + + GetStyleData(eStyleStruct_Display, + (const nsStyleStruct*&)styleDisplay); + + switch (styleDisplay->mOverflow) + { + case NS_STYLE_OVERFLOW_SCROLL: + *aScrollPreference = AlwaysScroll; + break; + + case NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL: + *aScrollPreference = AlwaysScrollHorizontal; + break; + + case NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL: + *aScrollPreference = AlwaysScrollVertical; + break; + + case NS_STYLE_OVERFLOW_AUTO: + *aScrollPreference = Auto; + break; + + default: + *aScrollPreference = NeverScroll; + } + + return NS_OK; +} + +/** +* Gets the size of the area that lies inside the scrollbars but clips the scrolled frame +*/ +NS_IMETHODIMP +nsGfxScrollFrame::GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const +{ + nsBoxLayoutState state(aPresContext); + + nsSize hs; + mInner->mHScrollbarBox->GetPrefSize(state, hs); + *aHbarHeight = hs.height; + + nsSize vs; + mInner->mVScrollbarBox->GetPrefSize(state, vs); + *aVbarWidth = vs.width; + + return NS_OK; +} + NS_IMETHODIMP nsGfxScrollFrame::SetScrollbarVisibility(nsIPresContext* aPresContext, PRBool aVerticalVisible, @@ -309,6 +390,10 @@ nsGfxScrollFrame::CreateAnonymousContent(nsIPresContext* aPresContext, elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content)); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, NS_ConvertToString("horizontal"), PR_FALSE); + + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + NS_ConvertToString("true"), PR_FALSE); + aAnonymousChildren.AppendElement(content); // create vertical scrollbar @@ -316,6 +401,10 @@ nsGfxScrollFrame::CreateAnonymousContent(nsIPresContext* aPresContext, elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content)); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, NS_ConvertToString("vertical"), PR_FALSE); + + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, + NS_ConvertToString("true"), PR_FALSE); + aAnonymousChildren.AppendElement(content); // XXX For GFX never have scrollbars @@ -368,37 +457,74 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, return rv; } + NS_IMETHODIMP nsGfxScrollFrame::AppendFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aFrameList) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) { - // Only one child frame allowed - return NS_ERROR_FAILURE; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + return frame->AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); } NS_IMETHODIMP nsGfxScrollFrame::InsertFrames(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aPrevFrame, - nsIFrame* aFrameList) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) { - // Only one child frame allowed - return NS_ERROR_FAILURE; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); } NS_IMETHODIMP nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, - nsIPresShell& aPresShell, - nsIAtom* aListName, - nsIFrame* aOldFrame) + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) { - // Scroll frame doesn't support incremental changes - return NS_ERROR_NOT_IMPLEMENTED; + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->RemoveFrame (aPresContext, + aPresShell, + aListName, + aOldFrame); } + +NS_IMETHODIMP +nsGfxScrollFrame::ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame) +{ + nsIFrame* frame; + mInner->mScrollAreaBox->GetFrame(&frame); + + return frame->ReplaceFrame (aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); +} + + + + NS_IMETHODIMP nsGfxScrollFrame::GetPadding(nsMargin& aMargin) { @@ -449,6 +575,22 @@ nsGfxScrollFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +NS_IMETHODIMP +nsGfxScrollFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) +{ + aAscent = 0; + nsresult rv = mInner->mScrollAreaBox->GetAscent(aState, aAscent); + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + aAscent += m.top; + GetMargin(m); + aAscent += m.top; + GetInset(m); + aAscent += m.top; + + return rv; +} + NS_IMETHODIMP nsGfxScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) @@ -506,8 +648,7 @@ nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) nsresult rv = mInner->mScrollAreaBox->GetMinSize(aState, aSize); - if (mInner->mHasVerticalScrollbar || - styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) { nsSize vSize(0,0); mInner->mVScrollbarBox->GetMinSize(aState, vSize); @@ -517,8 +658,7 @@ nsGfxScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) aSize.height = vSize.height; } - if (mInner->mHasHorizontalScrollbar || - styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || + if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) { nsSize hSize(0,0); mInner->mHScrollbarBox->GetMinSize(aState, hSize); @@ -580,7 +720,8 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, size->height = mInner->mMaxElementSize.height; else mInner->mMaxElementSize.height = size->height; - + + // make sure we add in our scrollbar. nsBoxLayoutState state(aPresContext, aReflowState, aDesiredSize); @@ -765,18 +906,83 @@ nsGfxScrollFrameInner::GetScrolledContentSize(nsSize& aSize) nsBox::AddInset(mScrollAreaBox, aSize); } -void -nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aRightOrBottom, PRBool aAdd) +PRBool +nsGfxScrollFrameInner::AddHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop) { - if ((aAdd && aHasScrollbar) || (!aAdd && !aHasScrollbar)) - return; - + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_TRUE); +} + +PRBool +nsGfxScrollFrameInner::AddVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE); +} + +PRBool +nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE); +} + +PRBool +nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight) +{ + return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE); +} + +PRBool +nsGfxScrollFrameInner::AddRemoveScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop, PRBool aHorizontal, PRBool aAdd) +{ + if (aHorizontal) { + if (mNeverHasHorizontalScrollbar) + return PR_FALSE; + + if (aAdd) + SetScrollbarVisibility(mHScrollbarBox, aAdd); + + nsSize hSize; + mHScrollbarBox->GetPrefSize(aState, hSize); + nsBox::AddMargin(mHScrollbarBox, hSize); + + if (!aAdd) + SetScrollbarVisibility(mHScrollbarBox, aAdd); + + PRBool fit = AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, hSize.height, aOnTop, aAdd); + if (!fit) + SetScrollbarVisibility(mHScrollbarBox, !aAdd); + + return fit; + } else { + if (mNeverHasVerticalScrollbar) + return PR_FALSE; + + if (aAdd) + SetScrollbarVisibility(mVScrollbarBox, aAdd); + + nsSize vSize; + mVScrollbarBox->GetPrefSize(aState, vSize); + + if (!aAdd) + SetScrollbarVisibility(mVScrollbarBox, aAdd); + + nsBox::AddMargin(mVScrollbarBox, vSize); + PRBool fit = AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, vSize.width, aOnTop, aAdd); + if (!fit) + SetScrollbarVisibility(mVScrollbarBox, !aAdd); + + return fit; + } +} + +PRBool +nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, nscoord& aSize, nscoord aSbSize, PRBool aRightOrBottom, PRBool aAdd) +{ nscoord size = aSize; if (size != NS_INTRINSICSIZE) { if (aAdd) { size -= aSbSize; - if (!aRightOrBottom) + if (!aRightOrBottom && size >= 0) aXY += aSbSize; } else { size += aSbSize; @@ -785,40 +991,16 @@ nsGfxScrollFrameInner::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY, n } } - // not enough room? If not don't do anything. + // not enough room? Yes? Return true. if (size >= aSbSize) { aHasScrollbar = aAdd; aSize = size; + return PR_TRUE; } -} -void -nsGfxScrollFrameInner::AddHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnTop) -{ - if (!mNeverHasHorizontalScrollbar) - AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, aSbSize.height, aOnTop, PR_TRUE); + return PR_FALSE; } -void -nsGfxScrollFrameInner::AddVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight) -{ - if (!mNeverHasVerticalScrollbar) - AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, aSbSize.width, aOnRight, PR_TRUE); -} - -void -nsGfxScrollFrameInner::RemoveHorizontalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnTop) -{ - AddRemoveScrollbar(mHasHorizontalScrollbar, aScrollAreaSize.y, aScrollAreaSize.height, aSbSize.height, aOnTop, PR_FALSE); -} - -void -nsGfxScrollFrameInner::RemoveVerticalScrollbar(const nsSize& aSbSize, nsRect& aScrollAreaSize, PRBool aOnRight) -{ - AddRemoveScrollbar(mHasVerticalScrollbar, aScrollAreaSize.x, aScrollAreaSize.width, aSbSize.width, aOnRight, PR_FALSE); -} - - nsresult nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect) { @@ -828,6 +1010,10 @@ nsGfxScrollFrameInner::LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const n NS_IMETHODIMP nsGfxScrollFrame::Layout(nsBoxLayoutState& aState) { + // mark ourselves as dirty so no child under us + // can post an incremental layout. + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; + PropagateDebug(aState); PRUint32 flags = 0; aState.GetLayoutFlags(flags); @@ -866,13 +1052,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsRect clientRect(0,0,0,0); mOuter->GetClientRect(clientRect); + // get the preferred size of the scrollbars nsSize hSize(0,0); nsSize vSize(0,0); - mHScrollbarBox->GetPrefSize(aState, hSize); - mVScrollbarBox->GetPrefSize(aState, vSize); nsSize hMinSize(0,0); nsSize vMinSize(0,0); + + /* + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); mHScrollbarBox->GetMinSize(aState, hMinSize); mVScrollbarBox->GetMinSize(aState, vMinSize); @@ -880,44 +1069,24 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBox::AddMargin(mVScrollbarBox, vSize); nsBox::AddMargin(mHScrollbarBox, hMinSize); nsBox::AddMargin(mVScrollbarBox, vMinSize); + */ // the scroll area size starts off as big as our content area nsRect scrollAreaRect(clientRect); - nsSize sbSize(vSize.width, hSize.height); - // Look at our style do we always have vertical or horizontal scrollbars? if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_HORIZONTAL) mHasHorizontalScrollbar = PR_TRUE; if (styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLL || styleDisplay->mOverflow == NS_STYLE_OVERFLOW_SCROLLBARS_VERTICAL) mHasVerticalScrollbar = PR_TRUE; - // see if we currenly have a vertical or horizotal scrollbar and subtract them - // from the scroll area size. - if (mHasHorizontalScrollbar) { - if (scrollAreaRect.height - sbSize.height < 0) - { - mHasHorizontalScrollbar = PR_FALSE; - mHScrollbarBox->Collapse(aState); - } else { - scrollAreaRect.height -= sbSize.height; - if (!scrollBarBottom) - scrollAreaRect.y += sbSize.height; - } - } + if (mHasHorizontalScrollbar) + AddHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom); - if (mHasVerticalScrollbar) { - if (scrollAreaRect.width - sbSize.width < 0) - { - mHasVerticalScrollbar = PR_FALSE; - mVScrollbarBox->Collapse(aState); - } else { - scrollAreaRect.width -= sbSize.width; - if (!scrollBarRight) - scrollAreaRect.x += sbSize.width; + if (mHasVerticalScrollbar) + AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight); + - } - } // layout our the scroll area LayoutBox(aState, mScrollAreaBox, scrollAreaRect); @@ -939,19 +1108,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) if (mHasVerticalScrollbar) { // We left room for the vertical scrollbar, but it's not needed; // remove it. - RemoveVerticalScrollbar(sbSize, scrollAreaRect, scrollBarRight); - needsLayout = PR_TRUE; - mVScrollbarBox->Collapse(aState); + if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) + needsLayout = PR_TRUE; } } else { if (!mHasVerticalScrollbar) { // We didn't leave room for the vertical scrollbar, but it turns // out we needed it - if (scrollAreaRect.width - sbSize.width >= 0) { - AddVerticalScrollbar(sbSize, scrollAreaRect, scrollBarRight); - mVScrollbarBox->UnCollapse(aState); + if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) needsLayout = PR_TRUE; - } + } } @@ -960,10 +1126,10 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBoxLayoutState resizeState(aState); resizeState.SetLayoutReason(nsBoxLayoutState::Resize); LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; } } - needsLayout = PR_FALSE; // if scrollbars are auto look at the horizontal case if ((NS_STYLE_OVERFLOW_SCROLL != styleDisplay->mOverflow) @@ -979,11 +1145,10 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) && styleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLLBARS_NONE) { if (!mHasHorizontalScrollbar) { - if (scrollAreaRect.height - sbSize.height >= 0) { - AddHorizontalScrollbar(sbSize, scrollAreaRect, scrollBarBottom); - mHScrollbarBox->UnCollapse(aState); + // no scrollbar? + if (AddHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) needsLayout = PR_TRUE; - } + // if we added a horizonal scrollbar and we did not have a vertical // there is a chance that by adding the horizonal scrollbar we will // suddenly need a vertical scrollbar. Is a special case but its @@ -996,9 +1161,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) // if the area is smaller or equal to and we have a scrollbar then // remove it. if (mHasHorizontalScrollbar) { - RemoveHorizontalScrollbar(sbSize, scrollAreaRect, scrollBarBottom); - mHScrollbarBox->Collapse(aState); - needsLayout = PR_TRUE; + if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) + needsLayout = PR_TRUE; } } } @@ -1008,6 +1172,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsBoxLayoutState resizeState(aState); resizeState.SetLayoutReason(nsBoxLayoutState::Resize); LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; } GetScrolledContentSize(scrolledContentSize); @@ -1030,6 +1195,8 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) nsIScrollableView* scrollable = GetScrollableView(presContext); scrollable->SetLineHeight(fontHeight); + mHScrollbarBox->GetPrefSize(aState, hSize); + mVScrollbarBox->GetPrefSize(aState, vSize); // layout vertical scrollbar nsRect vRect(clientRect); @@ -1054,10 +1221,15 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) } LayoutBox(aState, mVScrollbarBox, vRect); + mVScrollbarBox->GetPrefSize(aState, vSize); + mVScrollbarBox->GetMinSize(aState, vMinSize); - if (!mHasVerticalScrollbar || (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) - mVScrollbarBox->Collapse(aState); + if (mHasVerticalScrollbar && (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) { + if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) + needsLayout = PR_TRUE; + mVScrollbarBox->GetPrefSize(aState, vSize); + } // layout horizontal scrollbar nsRect hRect(clientRect); @@ -1083,10 +1255,23 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) } LayoutBox(aState, mHScrollbarBox, hRect); - - if (!mHasHorizontalScrollbar || (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { - mHScrollbarBox->Collapse(aState); + + mHScrollbarBox->GetMinSize(aState, hMinSize); + + if (mHasHorizontalScrollbar && (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) { + if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) + needsLayout = PR_TRUE; } + + // we only need to set the rect. The inner child stays the same size. + if (needsLayout) { + nsBoxLayoutState resizeState(aState); + resizeState.SetLayoutReason(nsBoxLayoutState::Resize); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); + needsLayout = PR_FALSE; + } + + return NS_OK; } @@ -1135,6 +1320,31 @@ nsGfxScrollFrameInner::SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, return PR_FALSE; } +void +nsGfxScrollFrameInner::SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible) +{ + nsIFrame* frame = nsnull; + aScrollbar->GetFrame(&frame); + + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + + PRBool old = PR_TRUE; + + nsAutoString value; + + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, value)) + old = PR_FALSE; + + if (aVisible == old) + return; + + if (!aVisible) + content->SetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, NS_ConvertToString("true"), PR_TRUE); + else + content->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::collapsed, PR_TRUE); +} + PRInt32 nsGfxScrollFrameInner::GetIntegerAttribute(nsIBox* aBox, nsIAtom* atom, PRInt32 defaultValue) { diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.h b/mozilla/layout/html/base/src/nsGfxScrollFrame.h index 48379349374..6b6d5f9341a 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.h +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.h @@ -79,6 +79,12 @@ public: nsIFrame* aPrevFrame, nsIFrame* aFrameList); + NS_IMETHOD ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame); + NS_IMETHOD Destroy(nsIPresContext* aPresContext); // This function returns NS_ERROR_NOT_IMPLEMENTED @@ -113,6 +119,8 @@ public: NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); + NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); NS_IMETHOD GetPadding(nsMargin& aPadding); @@ -122,12 +130,23 @@ public: NS_IMETHOD GetScrollbarVisibility(nsIPresContext* aPresContext, PRBool *aVerticalVisible, PRBool *aHorizontalVisible) const; + + NS_IMETHOD GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const; + NS_IMETHOD ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags); + NS_IMETHOD SetScrollbarVisibility(nsIPresContext* aPresContext, PRBool aVerticalVisible, PRBool aHorizontalVisible); NS_IMETHOD GetClipSize(nsIPresContext* aPresContext, nscoord *aWidth, nscoord *aHeight) const; + + NS_IMETHOD GetScrollPreference(nsScrollPref* aScrollPreference) const; + + NS_IMETHOD GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const; + /** * Get the "type" of the frame * diff --git a/mozilla/layout/html/base/src/nsScrollFrame.cpp b/mozilla/layout/html/base/src/nsScrollFrame.cpp index 30e596ae0a8..a74b0ed7380 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollFrame.cpp @@ -137,6 +137,51 @@ nsScrollFrame::GetClipSize( nsIPresContext* aPresContext, return NS_OK; } +/** + * Query whether scroll bars should be displayed all the time, never or + * only when necessary. + * @return current scrollbar selection + */ +NS_IMETHODIMP +nsScrollFrame::GetScrollPreference(nsScrollPref* aScrollPreference) const +{ + return NS_OK; +} + +/** +* Gets the size of the area that lies inside the scrollbars but clips the scrolled frame +*/ +NS_IMETHODIMP +nsScrollFrame::GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const +{ + return NS_OK; +} + +NS_IMETHODIMP +nsScrollFrame::GetScrollPosition(nsIPresContext* aPresContext, nscoord &aX, nscoord& aY) const +{ + nsIScrollableView* scrollingView; + nsIView* view; + GetView(aPresContext, &view); + NS_ASSERTION(NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView)), "No scrolling view"); + return scrollingView->GetScrollPosition(aX, aY); +} + +NS_IMETHODIMP +nsScrollFrame::ScrollTo(nsIPresContext* aPresContext, nscoord aX, nscoord aY, PRUint32 aFlags) +{ + nsIScrollableView* scrollingView; + nsIView* view; + GetView(aPresContext, &view); + + NS_ASSERTION(NS_SUCCEEDED(view->QueryInterface(kScrollViewIID, (void**)&scrollingView)), "No scrolling view"); + return scrollingView->ScrollTo(aX, aY, aFlags); + +} + + /** * Get information about whether the vertical and horizontal scrollbars diff --git a/mozilla/layout/html/base/src/nsScrollFrame.h b/mozilla/layout/html/base/src/nsScrollFrame.h index a6da11c0584..f6ec2394f65 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.h +++ b/mozilla/layout/html/base/src/nsScrollFrame.h @@ -88,6 +88,12 @@ public: nsFramePaintLayer aWhichLayer, nsIFrame** aFrame); + NS_IMETHOD GetScrollPreference(nsScrollPref* aScrollPreference) const; + + NS_IMETHOD GetScrollbarSizes(nsIPresContext* aPresContext, + nscoord *aVbarWidth, + nscoord *aHbarHeight) const; + /** * Get the "type" of the frame * @@ -110,6 +116,9 @@ public: nscoord *aWidth, nscoord *aHeight) const; + NS_IMETHOD GetScrollPosition(nsIPresContext* aContext, nscoord &aX, nscoord& aY) const; + NS_IMETHOD ScrollTo(nsIPresContext* aContext, nscoord aX, nscoord aY, PRUint32 aFlags); + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp index 2300909e73f..14407ddfb83 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp @@ -363,6 +363,23 @@ nsScrollPortFrame::Layout(nsBoxLayoutState& aState) return NS_OK; } +NS_IMETHODIMP +nsScrollPortFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) +{ + aAscent = 0; + nsIBox* child = nsnull; + GetChildBox(&child); + nsresult rv = child->GetAscent(aState, aAscent); + nsMargin m(0,0,0,0); + GetBorderAndPadding(m); + aAscent += m.top; + GetMargin(m); + aAscent += m.top; + GetInset(m); + aAscent += m.top; + + return rv; +} NS_IMETHODIMP nsScrollPortFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.h b/mozilla/layout/html/base/src/nsScrollPortFrame.h index 69d655335ae..b1df0207bb3 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.h +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.h @@ -91,6 +91,7 @@ public: NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); + NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent); NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState); NS_IMETHOD GetPadding(nsMargin& aMargin); NS_IMETHOD GetBorder(nsMargin& aMargin); diff --git a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp index 410c5fd12a4..4c3942391ea 100644 --- a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp @@ -70,6 +70,24 @@ public: const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame); + NS_IMETHOD ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame); #ifdef DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const { return MakeFrameName("FieldSet", aResult); @@ -553,3 +571,57 @@ nsFieldSetFrame::GetSkipSides() const return 0; } +NS_IMETHODIMP +nsFieldSetFrame::AppendFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aFrameList) +{ + return mContentFrame->AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); +} + +NS_IMETHODIMP +nsFieldSetFrame::InsertFrames(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + return mContentFrame->InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); +} + +NS_IMETHODIMP +nsFieldSetFrame::RemoveFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + return mContentFrame->RemoveFrame (aPresContext, + aPresShell, + aListName, + aOldFrame); +} + + +NS_IMETHODIMP +nsFieldSetFrame::ReplaceFrame(nsIPresContext* aPresContext, + nsIPresShell& aPresShell, + nsIAtom* aListName, + nsIFrame* aOldFrame, + nsIFrame* aNewFrame) +{ + return mContentFrame->ReplaceFrame (aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); +} + + diff --git a/mozilla/layout/xul/base/src/nsBox.cpp b/mozilla/layout/xul/base/src/nsBox.cpp index 5186ea36172..67a3baf5eb5 100644 --- a/mozilla/layout/xul/base/src/nsBox.cpp +++ b/mozilla/layout/xul/base/src/nsBox.cpp @@ -44,14 +44,114 @@ #include "nsHTMLAtoms.h" #include "nsXULAtoms.h" -#undef DEBUG_evaughan +//#define DEBUG_REFLOW -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED static PRInt32 coelesced = 0; +#endif +#ifdef DEBUG_REFLOW + +PRInt32 gIndent = 0; +PRInt32 gLayout = 0; + +void +nsBoxAddIndents() +{ + for(PRInt32 i=0; i < gIndent; i++) + { + printf(" "); + } +} + +void +nsBoxAppendAttribute(nsIContent* aContent, nsIAtom* aAtom, nsAutoString& aResult) +{ + nsAutoString att; + aContent->GetAttribute(kNameSpaceID_None, aAtom, att); + nsAutoString name; + aAtom->ToString(name); + aResult.AppendWithConversion("["); + aResult.Append(name); + aResult.AppendWithConversion("="); + aResult.Append(att); + aResult.AppendWithConversion("]"); +} + +#endif + +void +nsBox::ListBox(nsAutoString& aResult) +{ +#ifdef DEBUG_REFLOW + nsAutoString name; + nsIFrame* frame; + GetFrame(&frame); + GetBoxName(name); + + aResult.Append(name); + + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + + if (content) { + nsBoxAppendAttribute(content, nsHTMLAtoms::id, aResult); + nsBoxAppendAttribute(content, nsHTMLAtoms::kClass, aResult); + } +#endif +} + +void +nsBox::GetBoxName(nsAutoString& aName) +{ + aName.AssignWithConversion("Box"); +} + +void +nsBox::EnterLayout(nsBoxLayoutState& aState) +{ + #ifdef DEBUG_REFLOW + + nsBoxAddIndents(); + + nsAutoString reason; + switch(aState.GetLayoutReason()) + { + case nsBoxLayoutState::Dirty: + reason.AssignWithConversion("Dirty"); + break; + case nsBoxLayoutState::Initial: + reason.AssignWithConversion("Initial"); + break; + case nsBoxLayoutState::Resize: + reason.AssignWithConversion("Resize"); + break; + } + + char ch[100]; + reason.ToCString(ch,100); + printf("%s Layout: ", ch); + nsAutoString s; + ListBox(s); + s.ToCString(ch,100); + printf("%s\n",ch); + gIndent++; + #endif +} + +void +nsBox::ExitLayout(nsBoxLayoutState& aState) +{ + #ifdef DEBUG_REFLOW + --gIndent; + #endif +} + +#ifdef REFLOW_COELESCED void Coelesced() { printf("Coelesed=%d\n", ++coelesced); + } #endif @@ -108,7 +208,7 @@ nsBox::MarkDirty(nsBoxLayoutState& aState) // only reflow if we aren't already dirty. if (state & NS_FRAME_IS_DIRTY) { -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED Coelesced(); #endif return NS_OK; @@ -123,7 +223,7 @@ nsBox::MarkDirty(nsBoxLayoutState& aState) layout->BecameDirty(this, aState); if (state & NS_FRAME_HAS_DIRTY_CHILDREN) { -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED Coelesced(); #endif return NS_OK; @@ -212,7 +312,7 @@ nsBox::MarkChildrenStyleChange() { // only reflow if we aren't already dirty. if (HasStyleChange()) { -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED printf("StyleChange reflows coelesced=%d\n", ++StyleCoelesced); #endif return NS_OK; @@ -269,7 +369,7 @@ nsBox::RelayoutStyleChange(nsBoxLayoutState& aState, nsIBox* aChild) return NS_OK; } } else { -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED Coelesced(); #endif } @@ -312,7 +412,7 @@ nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild) return parent->ReflowDirtyChild(shell, frame); } } else { -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED Coelesced(); #endif } @@ -817,8 +917,12 @@ nsBox::IsCollapsed(nsBoxLayoutState& aState, PRBool& aCollapsed) NS_IMETHODIMP nsBox::Layout(nsBoxLayoutState& aState) { + EnterLayout(aState); + SyncLayout(aState); + ExitLayout(aState); + return NS_OK; } @@ -1296,6 +1400,7 @@ nsBox::GetDefaultFlex(PRInt32& aFlex) return PR_TRUE; } + // nsISupports NS_IMETHODIMP_(nsrefcnt) nsBox::AddRef(void) diff --git a/mozilla/layout/xul/base/src/nsBox.h b/mozilla/layout/xul/base/src/nsBox.h index 833a3709235..ccebeee0d0c 100644 --- a/mozilla/layout/xul/base/src/nsBox.h +++ b/mozilla/layout/xul/base/src/nsBox.h @@ -117,6 +117,11 @@ protected: virtual PRBool GetDefaultFlex(PRInt32& aFlex); virtual void GetLayoutFlags(PRUint32& aFlags); + void EnterLayout(nsBoxLayoutState& aState); + void ExitLayout(nsBoxLayoutState& aState); + virtual void GetBoxName(nsAutoString& aName); + virtual void ListBox(nsAutoString& aResult); + enum eMouseThrough { unset, never, diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.cpp b/mozilla/layout/xul/base/src/nsBoxFrame.cpp index 75bf8a2cd76..6232dcae0de 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsBoxFrame.cpp @@ -75,11 +75,8 @@ #include "nsIBoxLayout.h" #include "nsSprocketLayout.h" -#undef DEBUG_evaughan - -#define CONSTANT 0 -//#define DEBUG_REFLOW //define DEBUG_REDRAW + #define DEBUG_SPRING_SIZE 8 #define DEBUG_BORDER_SIZE 2 #define COIL_SIZE 8 @@ -131,11 +128,13 @@ public: void GetDebugPref(nsIPresContext* aPresContext); + /* nsresult PaintDebug(nsIBox* aBox, nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); +*/ nsresult DisplayDebugInfoFor(nsIBox* aBox, nsIPresContext* aPresContext, @@ -160,8 +159,8 @@ public: nsBoxFrame::Halignment GetHAlign(); nsBoxFrame::Valignment GetVAlign(); + // instance variables. nsBoxFrame* mOuter; - nscoord mInnerSize; nsBoxFrame::Valignment mValign; nsBoxFrame::Halignment mHalign; @@ -176,22 +175,11 @@ public: static PRBool gDebug; static nsIBox* mDebugChild; -#ifdef DEBUG_REFLOW - PRInt32 reflowCount; -#endif - }; PRBool nsBoxFrameInner::gDebug = PR_FALSE; nsIBox* nsBoxFrameInner::mDebugChild = nsnull; -#ifdef DEBUG_REFLOW - -PRInt32 gIndent = 0; -PRInt32 gReflows = 0; - -#endif - nsresult NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal) { @@ -227,15 +215,9 @@ nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* a mInner->mValign = nsBoxFrame::vAlign_Top; mInner->mHalign = nsBoxFrame::hAlign_Left; - mInner->mInnerSize = 0; NeedsRecalc(); - -#ifdef DEBUG_REFLOW - mInner->reflowCount = 100; -#endif - // if no layout manager specified us the static sprocket layout nsCOMPtr layout = aLayoutManager; @@ -246,10 +228,6 @@ nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* a SetLayoutManager(layout); NeedsRecalc(); - -#ifdef DEBUG_REFLOW - mInner->reflowCount = 100; -#endif } nsBoxFrame::~nsBoxFrame() @@ -613,9 +591,6 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsBoxFrame", aReflowState.reason); - #ifdef DEBUG_REFLOW - gIndent++; - #endif NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0"); @@ -817,21 +792,14 @@ nsBoxFrame::PropagateDebug(nsBoxLayoutState& aState) NS_IMETHODIMP nsBoxFrame::Layout(nsBoxLayoutState& aState) { + // mark ourselves as dirty so no child under us + // can post an incremental layout. + mState |= NS_FRAME_HAS_DIRTY_CHILDREN; PropagateDebug(aState); - return nsContainerBox::Layout(aState); -} + nsresult rv = nsContainerBox::Layout(aState); - -#ifdef DEBUG_REFLOW -void -nsBoxFrameInner::AddIndents() -{ - for(PRInt32 i=0; i < gIndent; i++) - { - printf(" "); - } + return rv; } -#endif nsBoxFrame::Valignment nsBoxFrameInner::GetVAlign() @@ -1086,7 +1054,7 @@ nsBoxFrame::GetInset(nsMargin& margin) return NS_OK; } -#ifdef DEBUG_evaughan +#ifdef DEBUG_COELESCED static PRInt32 StyleCoelesced = 0; #endif @@ -1099,8 +1067,10 @@ nsBoxFrame::HasStyleChange() void nsBoxFrame::SetStyleChangeFlag(PRBool aDirty) { + nsBox::SetStyleChangeFlag(aDirty); + if (aDirty) - mState |= (NS_STATE_STYLE_CHANGE | NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN); + mState |= (NS_STATE_STYLE_CHANGE); else mState &= ~NS_STATE_STYLE_CHANGE; } @@ -1123,10 +1093,7 @@ nsBoxFrame :: Paint ( nsIPresContext* aPresContext, const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); - // if we aren't visible then we are done. - if (!disp->IsVisibleOrCollapsed()) - return NS_OK; - + // if collapsed nothing is drawn if (disp->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) return NS_OK; @@ -1240,6 +1207,24 @@ nsBoxFrame::PaintChildren(nsIPresContext* aPresContext, r.y = r.y + r.height - debugBorder.bottom; r.height = debugBorder.bottom; aRenderingContext.FillRect(r); + + + // if we have dirty children or we are dirty + // place a green border around us. + PRBool dirty = PR_FALSE; + IsDirty(dirty); + PRBool dirtyc = PR_FALSE; + HasDirtyChildren(dirtyc); + + if (dirty || dirtyc) { + IsDirty(dirty); + HasDirtyChildren(dirty); + + nsRect dirtyr(inner); + aRenderingContext.SetColor(NS_RGB(0,255,0)); + aRenderingContext.DrawRect(dirtyr); + aRenderingContext.SetColor(color); + } } @@ -1400,20 +1385,16 @@ nsBoxFrame::GetFrame(nsIFrame** aFrame) return NS_OK; } +void +nsBoxFrame::GetBoxName(nsAutoString& aName) +{ + GetFrameName(aName); +} + NS_IMETHODIMP nsBoxFrame::GetFrameName(nsString& aResult) const { - nsCOMPtr content; - nsBoxFrame* box = (nsBoxFrame*)this; - box->GetContentOf(getter_AddRefs(content)); - nsAutoString id; - - if (content) - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); - - aResult.AssignWithConversion("Box[id="); - aResult.Append(id); - aResult.AppendWithConversion("]"); + aResult.AssignWithConversion("Box"); return NS_OK; } @@ -1430,9 +1411,18 @@ nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; + const nsStyleDisplay* disp = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + if (disp->mVisible == NS_STYLE_VISIBILITY_COLLAPSE) + return NS_ERROR_FAILURE; + nsIView* view = nsnull; GetView(aPresContext, &view); @@ -1491,8 +1481,6 @@ nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, } // if no kids were hit then select us - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); if (disp->IsVisible()) { *aFrame = this; return NS_OK; @@ -1670,7 +1658,7 @@ nsBoxFrameInner::operator delete(void* aPtr, size_t sz) nsBoxLayoutState::Free(aPtr, sz); } - +/* nsresult nsBoxFrameInner::PaintDebug(nsIBox* aBox, @@ -1737,6 +1725,19 @@ nsBoxFrameInner::PaintDebug(nsIBox* aBox, r.height = debugBorder.bottom; aRenderingContext.FillRect(r); + // if we have dirty children or we are dirty + // place a green border around us. + PRBool dirty = PR_FALSE; + mOuter->IsDirty(dirty); + PRBool dirtyc = PR_FALSE; + mOuter->HasDirtyChildren(dirty); + + if (dirty || dirtyc) { + nsRect dirtyr(inner); + aRenderingContext.SetColor(NS_RGB(0,255,0)); + aRenderingContext.DrawRect(dirtyr); + } + // paint the springs. nscoord x, y, borderSize, springSize; @@ -1771,17 +1772,7 @@ nsBoxFrameInner::PaintDebug(nsIBox* aBox, else borderSize = size.height; - /* - if (mDebugChild == info->frame) - { - aRenderingContext.SetColor(NS_RGB(0,255,0)); - if (mOuter->mInner->mHorizontal) - aRenderingContext.FillRect(x, inner.y, size.width, debugBorder.top); - else - aRenderingContext.FillRect(inner.x, x, size.height, debugBorder.left); - aRenderingContext.SetColor(debugColor->mColor); - } - */ + nscoord flex = 0; box->GetFlex(state, flex); @@ -1794,7 +1785,7 @@ nsBoxFrameInner::PaintDebug(nsIBox* aBox, return NS_OK; } - +*/ void nsBoxFrameInner::DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2) diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.h b/mozilla/layout/xul/base/src/nsBoxFrame.h index 9794a335db5..0a01eeb12c3 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsBoxFrame.h @@ -170,6 +170,8 @@ public: nsBoxFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE); protected: + virtual void GetBoxName(nsAutoString& aName); + virtual PRBool HasStyleChange(); virtual void SetStyleChangeFlag(PRBool aDirty); diff --git a/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp b/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp index d9c0a4f79f2..b2c67eee6a1 100644 --- a/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp +++ b/mozilla/layout/xul/base/src/nsBoxLayoutState.cpp @@ -53,6 +53,8 @@ nsBoxLayoutState::nsBoxLayoutState(const nsBoxLayoutState& aState) mType = aState.mType; mReflowState = aState.mReflowState; mMaxElementSize = aState.mMaxElementSize; + mOverFlowSize = aState.mOverFlowSize; + mLayoutFlags = aState.mLayoutFlags; } nsBoxLayoutState::nsBoxLayoutState(nsIPresShell* aShell):mReflowState(nsnull), diff --git a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp index 98e6f3efa3c..61e043a1cf5 100644 --- a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp +++ b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.cpp @@ -54,8 +54,69 @@ #include "nsILineIterator.h" #include "nsIFontMetrics.h" +//#define DEBUG_REFLOW + +#ifdef DEBUG_REFLOW +PRInt32 gIndent = 0; + +void +nsAdaptorAddIndents() +{ + for(PRInt32 i=0; i < gIndent; i++) + { + printf(" "); + } +} + +void +nsAdaptorPrintReason(nsHTMLReflowState& aReflowState) +{ + char* reflowReasonString; + + switch(aReflowState.reason) + { + case eReflowReason_Initial: + reflowReasonString = "initial"; + break; + + case eReflowReason_Resize: + reflowReasonString = "resize"; + break; + case eReflowReason_Dirty: + reflowReasonString = "dirty"; + break; + case eReflowReason_StyleChange: + reflowReasonString = "stylechange"; + break; + case eReflowReason_Incremental: + { + nsIReflowCommand::ReflowType type; + aReflowState.reflowCommand->GetType(type); + switch (type) { + case nsIReflowCommand::StyleChanged: + reflowReasonString = "incremental (StyleChanged)"; + break; + case nsIReflowCommand::ReflowDirty: + reflowReasonString = "incremental (ReflowDirty)"; + break; + default: + reflowReasonString = "incremental (Unknown)"; + } + } + break; + default: + reflowReasonString = "unknown"; + break; + } + + printf("%s",reflowReasonString); +} + +#endif + nsBoxToBlockAdaptor::nsBoxToBlockAdaptor(nsIPresShell* aPresShell, nsIFrame* aFrame):nsBox(aPresShell) { + mSizeSet = PR_FALSE; mFrame = aFrame; mSpaceManager = nsnull; mWasCollapsed = PR_FALSE; @@ -117,15 +178,7 @@ nsBoxToBlockAdaptor::~nsBoxToBlockAdaptor() NS_IMETHODIMP nsBoxToBlockAdaptor::NeedsRecalc() { - /* nsIBox* parent; - GetParentBox(&parent); - nsIFrame* frame; - if (parent) { - parent->GetFrame(&frame); - nsFrameState frameState = 0; - frame->GetFrameState(&frameState); - }*/ - + mSizeSet = PR_FALSE; mMinWidth = -1; mPrefNeedsRecalc = PR_TRUE; SizeNeedsRecalc(mMinSize); @@ -162,6 +215,12 @@ nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) PRBool isDirty = PR_FALSE; IsDirty(isDirty); + // if the size has already been set get the + // current size so we can set it back. + nsRect oldRect(0,0,0,0); + if (mSizeSet) + GetBounds(oldRect); + nsSize* currentSize = nsnull; aState.GetMaxElementSize(¤tSize); nsSize size(0,0); @@ -193,6 +252,12 @@ nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) mCachedMaxElementHeight = size.height; } + // set it back + if (mSizeSet) { + SetBounds(aState, oldRect); + Layout(aState); + } + nsFrameState frameState = 0; mFrame->GetFrameState(&frameState); frameState |= NS_FRAME_IS_DIRTY; @@ -346,6 +411,8 @@ nsBoxToBlockAdaptor::Layout(nsBoxLayoutState& aState) SyncLayout(aState); + mSizeSet = PR_TRUE; + return rv; } @@ -363,9 +430,16 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, { DO_GLOBAL_REFLOW_COUNT("nsBoxToBlockAdaptor", aReflowState.reason); - //printf("width=%d, height=%d\n", aWidth, aHeight); +#ifdef DEBUG_REFLOW + nsAdaptorAddIndents(); + printf("Reflowing: "); + nsFrame::ListTag(stdout, mFrame); + printf("\n"); + gIndent++; +#endif - nsIBox* parent; + //printf("width=%d, height=%d\n", aWidth, aHeight); + nsIBox* parent; GetParentBox(&parent); nsIFrame* frame; parent->GetFrame(&frame); @@ -558,41 +632,6 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, // create a reflow state to tell our child to flow at the given size. -#ifdef DEBUG_REFLOW - - char* reflowReasonString; - - switch(reason) - { - case eReflowReason_Initial: - reflowReasonString = "initial"; - break; - - case eReflowReason_Resize: - reflowReasonString = "resize"; - break; - case eReflowReason_Dirty: - reflowReasonString = "dirty"; - break; - case eReflowReason_StyleChange: - reflowReasonString = "stylechange"; - break; - case eReflowReason_Incremental: - reflowReasonString = "incremental"; - break; - default: - reflowReasonString = "unknown"; - break; - } - - AddIndents(); - nsFrame::ListTag(stdout, childFrame); - char ch[100]; - aReason.ToCString(ch,100); - - printf(" reason=%s %s",reflowReasonString,ch); -#endif - if (size.height != NS_INTRINSICSIZE) { size.height -= (border.top + border.bottom); NS_ASSERTION(size.height >= 0,"Error top bottom border too large"); @@ -611,10 +650,6 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, // XXX this needs to subtract out the border and padding of mFrame since it is content size reflowState.mComputedWidth = size.width; reflowState.mComputedHeight = size.height; -#ifdef DEBUG_REFLOW - printf(" Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); -#endif - // if (aMoveFrame) { // PlaceChild(aPresContext, mFrame, aX + margin.left, aY + margin.top); @@ -640,6 +675,14 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, reflowState.reflowCommand->GetType(type); if (type != nsIReflowCommand::StyleChanged) { + #ifdef DEBUG_REFLOW + nsAdaptorAddIndents(); + printf("Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); + nsAdaptorAddIndents(); + nsAdaptorPrintReason(reflowState); + printf("\n"); + #endif + mFrame->WillReflow(aPresContext); mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); mFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); @@ -652,6 +695,15 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, mStyleChange = PR_FALSE; } + + #ifdef DEBUG_REFLOW + nsAdaptorAddIndents(); + printf("Size=(%d,%d)\n",reflowState.mComputedWidth, reflowState.mComputedHeight); + nsAdaptorAddIndents(); + nsAdaptorPrintReason(reflowState); + printf("\n"); + #endif + // place the child and reflow mFrame->WillReflow(aPresContext); @@ -710,6 +762,11 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, reflowState.reason = eReflowReason_Resize; reflowState.reflowCommand = nsnull; mFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + #ifdef DEBUG_REFLOW + nsAdaptorAddIndents(); + nsAdaptorPrintReason(reflowState); + printf("\n"); + #endif mFrame->WillReflow(aPresContext); mFrame->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); mFrame->GetFrameState(&kidState); @@ -822,18 +879,14 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, #ifdef DEBUG_REFLOW if (aHeight != NS_INTRINSICSIZE && aDesiredSize.height != aHeight) { - AddIndents(); - printf("**** Child "); - nsFrame::ListTag(stdout, childFrame); - printf(" got taller!******\n"); + nsAdaptorAddIndents(); + printf("*****got taller!*****\n"); } if (aWidth != NS_INTRINSICSIZE && aDesiredSize.width != aWidth) { - AddIndents(); - printf("**** Child "); - nsFrame::ListTag(stdout, childFrame); - printf(" got wider!******\n"); + nsAdaptorAddIndents(); + printf("*****got wider!******\n"); } #endif @@ -851,7 +904,11 @@ nsBoxToBlockAdaptor::Reflow(nsBoxLayoutState& aState, mMinWidth = aDesiredSize.width; SizeNeedsRecalc(mMinSize); } - + +#ifdef DEBUG_REFLOW + gIndent--; +#endif + return NS_OK; } diff --git a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h index b350916f0c1..98c5c99ba21 100644 --- a/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h +++ b/mozilla/layout/xul/base/src/nsBoxToBlockAdaptor.h @@ -88,6 +88,7 @@ protected: PRBool mWasCollapsed; nscoord mCachedMaxElementHeight; PRBool mStyleChange; + PRBool mSizeSet; }; #endif diff --git a/mozilla/layout/xul/base/src/nsContainerBox.cpp b/mozilla/layout/xul/base/src/nsContainerBox.cpp index ee0a2707f49..55665bcbd78 100644 --- a/mozilla/layout/xul/base/src/nsContainerBox.cpp +++ b/mozilla/layout/xul/base/src/nsContainerBox.cpp @@ -75,6 +75,12 @@ nsContainerBox::nsContainerBox(nsIPresShell* aShell):nsBox(aShell) mInsertionPoint = nsnull; } +void +nsContainerBox::GetBoxName(nsAutoString& aName) +{ + aName.AssignWithConversion("ContainerBox"); +} + NS_IMETHODIMP nsContainerBox::GetChildBox(nsIBox** aBox) { @@ -514,17 +520,22 @@ nsContainerBox::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) NS_IMETHODIMP nsContainerBox::Layout(nsBoxLayoutState& aState) { + EnterLayout(aState); + nsresult rv = NS_OK; PRUint32 oldFlags = 0; aState.GetLayoutFlags(oldFlags); + aState.SetLayoutFlags(0); if (mLayoutManager) rv = mLayoutManager->Layout(this, aState); aState.SetLayoutFlags(oldFlags); - nsBox::Layout(aState); + SyncLayout(aState); + + ExitLayout(aState); return rv; } diff --git a/mozilla/layout/xul/base/src/nsContainerBox.h b/mozilla/layout/xul/base/src/nsContainerBox.h index 519211bc944..70a08dde361 100644 --- a/mozilla/layout/xul/base/src/nsContainerBox.h +++ b/mozilla/layout/xul/base/src/nsContainerBox.h @@ -74,6 +74,8 @@ protected: virtual nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); //virtual nsresult LayoutChildAt(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect, PRUint32 aFlags); + virtual void GetBoxName(nsAutoString& aName); + nsIBox* mFirstChild; nsIBox* mLastChild; PRInt32 mChildCount; diff --git a/mozilla/layout/xul/base/src/nsDeckFrame.cpp b/mozilla/layout/xul/base/src/nsDeckFrame.cpp index 28bf1895b46..cee3e00d50c 100644 --- a/mozilla/layout/xul/base/src/nsDeckFrame.cpp +++ b/mozilla/layout/xul/base/src/nsDeckFrame.cpp @@ -165,6 +165,10 @@ NS_IMETHODIMP nsDeckFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + // if it is not inside us fail if (!mRect.Contains(aPoint)) { return NS_ERROR_FAILURE; diff --git a/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp b/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp index 0eb781d6ce7..9276a909396 100644 --- a/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -67,6 +67,13 @@ nsLeafBoxFrame::nsLeafBoxFrame(nsIPresShell* aShell):nsBox(aShell) { } +void +nsLeafBoxFrame::GetBoxName(nsAutoString& aName) +{ + GetFrameName(aName); +} + + /** * Initialize us. This is a good time to get the alignment of the box */ @@ -101,6 +108,9 @@ nsLeafBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; diff --git a/mozilla/layout/xul/base/src/nsLeafBoxFrame.h b/mozilla/layout/xul/base/src/nsLeafBoxFrame.h index ebab9d1b2e4..5e9dc6d9788 100644 --- a/mozilla/layout/xul/base/src/nsLeafBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsLeafBoxFrame.h @@ -66,6 +66,8 @@ public: protected: + virtual void GetBoxName(nsAutoString& aName); + virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize) {} diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index bf819ded888..1dd2a1d565e 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -57,6 +57,8 @@ #include "nsWidgetsCID.h" #include "nsBoxLayoutState.h" #include "nsIXBLBinding.h" +#include "nsIScrollableFrame.h" +#include "nsIViewManager.h" #include "nsIBindingManager.h" #define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) @@ -119,7 +121,8 @@ nsMenuFrame::nsMenuFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mChecked(PR_FALSE), mType(eMenuType_Normal), mMenuParent(nsnull), - mPresContext(nsnull) + mPresContext(nsnull), + mLastPref(-1,-1) { } // cntr @@ -222,6 +225,10 @@ nsMenuFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + // if it is not inside us or not in the layer in which we paint, fail if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; @@ -440,24 +447,45 @@ nsMenuFrame::MarkAsGenerated() NS_IMETHODIMP nsMenuFrame::ActivateMenu(PRBool aActivateFlag) { - // Activate the menu without opening it. - nsCOMPtr child; - GetMenuChildrenElement(getter_AddRefs(child)); + nsIFrame* frame = mPopupFrames.FirstChild(); + nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame; + + if (!menuPopup) + return NS_OK; - // We've got some children for real. - if (child) { - // When we sync the popup view with the frame, we'll show the popup if |menutobedisplayed| - // is set by setting the |menuactive| attribute. This trips CSS to make the view visible. - // We wait until the last possible moment to show to avoid flashing, but we can just go - // ahead and hide it here if we're told to (no additional stages necessary). - if (aActivateFlag) - child->SetAttribute(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, NS_ConvertASCIItoUCS2("true"), PR_TRUE); - else { - child->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE); - child->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE); - } + + if (aActivateFlag) { + nsRect rect; + menuPopup->GetRect(rect); + nsIView* view = nsnull; + menuPopup->GetView(mPresContext, &view); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->ResizeView(view, rect.width, rect.height); + + // make sure the scrolled window is at 0,0 + if (mLastPref.height <= rect.height) { + nsIBox* child; + menuPopup->GetChildBox(&child); + + nsCOMPtr scrollframe = do_QueryInterface(child); + if (scrollframe) { + scrollframe->ScrollTo(mPresContext, 0, 0); + } + } + + viewManager->UpdateView(view, nsRect(0,0, rect.width, rect.height), NS_VMREFRESH_IMMEDIATE); + viewManager->SetViewVisibility(view, nsViewVisibility_kShow); + + } else { + nsIView* view = nsnull; + menuPopup->GetView(mPresContext, &view); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->SetViewVisibility(view, nsViewVisibility_kHide); + viewManager->ResizeView(view, 0, 0); } - + return NS_OK; } @@ -523,9 +551,9 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag) nsIFrame* frame = mPopupFrames.FirstChild(); nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame; - - ActivateMenu(PR_TRUE); - + + mMenuOpen = PR_TRUE; + if (menuPopup) { // Install a keyboard navigation listener if we're the root of the menu chain. PRBool onMenuBar = PR_TRUE; @@ -588,20 +616,54 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag) popupAlign.AssignWithConversion("topleft"); } + // if height never set we need to do an initial reflow. + if (mLastPref.height == -1) + { + nsBoxLayoutState state(mPresContext); + menuPopup->MarkDirty(state); + + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + shell->FlushPendingNotifications(); + } + + nsRect curRect; + menuPopup->GetRect(curRect); + + menuPopup->SetRect(mPresContext, nsRect(0,0,mLastPref.width, mLastPref.height)); + + nsIView* view = nsnull; + menuPopup->GetView(mPresContext, &view); + view->SetVisibility(nsViewVisibility_kHide); menuPopup->SyncViewWithFrame(mPresContext, popupAnchor, popupAlign, this, -1, -1); + nsRect rect; + menuPopup->GetRect(rect); + + // if the height is different then reflow. It might need scrollbars force a reflow + if (curRect.height != rect.height || mLastPref.height != rect.height) + { + nsBoxLayoutState state(mPresContext); + menuPopup->MarkDirty(state); + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + shell->FlushPendingNotifications(); + menuPopup->GetRect(rect); + } + + ActivateMenu(PR_TRUE); + + nsCOMPtr childPopup = do_QueryInterface(frame); + UpdateDismissalListener(childPopup); + } - nsCOMPtr childPopup = do_QueryInterface(frame); - UpdateDismissalListener(childPopup); - - mMenuOpen = PR_TRUE; - // Set the focus back to our view's widget. if (nsMenuFrame::mDismissalListener) nsMenuFrame::mDismissalListener->EnableListener(PR_TRUE); } else { + // Close the menu. // Execute the ondestroy handler, but only if we're actually open if ( !mMenuOpen || !OnDestroy() ) @@ -634,20 +696,12 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag) ActivateMenu(PR_FALSE); mMenuOpen = PR_FALSE; -/* - nsIView* view; - GetView(&view); - if (!view) { - nsPoint offset; - GetOffsetFromView(offset, &view); - } - nsCOMPtr widget; - view->GetWidget(*getter_AddRefs(widget)); - widget->SetFocus(); -*/ + if (nsMenuFrame::mDismissalListener) nsMenuFrame::mDismissalListener->EnableListener(PR_TRUE); + } + } void @@ -700,18 +754,84 @@ nsMenuFrame::Layout(nsBoxLayoutState& aState) BoundsCheck(minSize, prefSize, maxSize); - AddMargin(ibox, prefSize); - if (menulist && prefSize.width < contentRect.width) prefSize.width = contentRect.width; - // lay it out but make sure we don't move the view. - LayoutChildAt(aState, ibox, nsRect(0,0,prefSize.width, prefSize.height)); + // if the pref size changed then set bounds to be the pref size + // and sync the view. And set new pref size. + if (mLastPref != prefSize) { + ibox->SetBounds(aState, nsRect(0,0,prefSize.width, prefSize.height)); + RePositionPopup(aState); + mLastPref = prefSize; + } + + // is the new size too small? Make sure we handle scrollbars correctly + nsIBox* child; + ibox->GetChildBox(&child); + + nsRect bounds(0,0,0,0); + ibox->GetBounds(bounds); + + nsCOMPtr scrollframe = do_QueryInterface(child); + if (scrollframe) { + nsIScrollableFrame::nsScrollPref pref; + scrollframe->GetScrollPreference(&pref); + + if (pref == nsIScrollableFrame::Auto) + { + // if our pref height + if (bounds.height < prefSize.height) { + // layout the child + ibox->Layout(aState); + + nscoord width; + nscoord height; + scrollframe->GetScrollbarSizes(aState.GetPresContext(), &width, &height); + if (bounds.width < prefSize.width + width) + { + bounds.width += width; + //printf("Width=%d\n",width); + ibox->SetBounds(aState, bounds); + } + } + } + } + + // layout the child + ibox->Layout(aState); + + // Only size the popups view if open. + if (mMenuOpen) { + nsIView* view = nsnull; + popupChild->GetView(aState.GetPresContext(), &view); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->ResizeView(view, bounds.width, bounds.height); + } + } SyncLayout(aState); - LayoutFinished(aState); + return rv; +} + +NS_IMETHODIMP +nsMenuFrame::MarkChildrenStyleChange() +{ + nsresult rv = nsBoxFrame::MarkChildrenStyleChange(); + if (NS_FAILED(rv)) + return rv; + + nsIFrame* popupChild = mPopupFrames.FirstChild(); + + if (popupChild) { + nsIBox* ibox = nsnull; + nsresult rv2 = popupChild->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox); + NS_ASSERTION(NS_SUCCEEDED(rv2) && ibox,"popupChild is not box!!"); + + return ibox->MarkChildrenStyleChange(); + } return rv; } @@ -868,8 +988,10 @@ nsMenuFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug) void -nsMenuFrame::LayoutFinished(nsBoxLayoutState& aState) +nsMenuFrame::RePositionPopup(nsBoxLayoutState& aState) { + nsIPresContext* presContext = aState.GetPresContext(); + // Sync up the view. nsIFrame* frame = mPopupFrames.FirstChild(); nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame; @@ -898,10 +1020,8 @@ nsMenuFrame::LayoutFinished(nsBoxLayoutState& aState) popupAlign.AssignWithConversion("topleft"); } - nsIPresContext* presContext = aState.GetPresContext(); menuPopup->SyncViewWithFrame(presContext, popupAnchor, popupAlign, this, -1, -1); } - } NS_IMETHODIMP @@ -1374,7 +1494,11 @@ nsMenuFrame::InsertFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::menupopup) { + nsCOMPtr menupopup = do_QueryInterface(aFrameList); + NS_ASSERTION(menupopup,"Popup is not a box!!!"); + menupopup->SetParentBox(this); mPopupFrames.InsertFrames(nsnull, nsnull, aFrameList); + nsBoxLayoutState state(aPresContext); SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); rv = MarkDirtyChildren(state); @@ -1402,6 +1526,10 @@ nsMenuFrame::AppendFrames(nsIPresContext* aPresContext, frameChild->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::menupopup) { + nsCOMPtr menupopup = do_QueryInterface(aFrameList); + NS_ASSERTION(menupopup,"Popup is not a box!!!"); + menupopup->SetParentBox(this); + mPopupFrames.AppendFrames(nsnull, aFrameList); nsBoxLayoutState state(aPresContext); SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG); diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index b676532d740..d1fd8f8f036 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -139,7 +139,7 @@ public: NS_IMETHOD GetMenuChild(nsIFrame** aResult) { *aResult = mPopupFrames.FirstChild(); return NS_OK; } NS_IMETHOD GetRadioGroupName(nsString &aName) { aName = mGroupName; return NS_OK; }; NS_IMETHOD GetMenuType(nsMenuType &aType) { aType = mType; return NS_OK; }; - + NS_IMETHOD MarkChildrenStyleChange(); NS_IMETHOD MarkAsGenerated(); // nsMenuFrame methods @@ -161,7 +161,7 @@ public: protected: - virtual void LayoutFinished(nsBoxLayoutState& aState); + virtual void RePositionPopup(nsBoxLayoutState& aState); static void UpdateDismissalListener(nsIMenuParent* aMenuParent); void UpdateMenuType(nsIPresContext* aPresContext); @@ -203,7 +203,7 @@ protected: nsCOMPtr mOpenTimer; nsIPresContext* mPresContext; // Our pres context. nsString mGroupName; - + nsSize mLastPref; public: static nsMenuDismissalListener* mDismissalListener; // The listener that dismisses menus. }; // class nsMenuFrame diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp index 379d72bc7b8..37d950f7634 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -50,7 +50,7 @@ #include "nsIDOMXULDocument.h" #include "nsILookAndFeel.h" #include "nsIComponentManager.h" - +#include "nsBoxLayoutState.h" static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); @@ -188,7 +188,7 @@ nsMenuPopupFrame::Init(nsIPresContext* aPresContext, void nsMenuPopupFrame::GetLayoutFlags(PRUint32& aFlags) { - aFlags = NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_MOVE_VIEW | NS_FRAME_NO_MOVE_CHILD_VIEWS; + aFlags = NS_FRAME_NO_SIZE_VIEW | NS_FRAME_NO_MOVE_VIEW /*| NS_FRAME_NO_MOVE_CHILD_VIEWS*/ ; } PRBool @@ -723,7 +723,7 @@ nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext* aPresContext, // finally move and resize it viewManager->MoveViewTo(view, xpos, ypos); - viewManager->ResizeView(view, mRect.width, mRect.height); + //viewManager->ResizeView(view, mRect.width, mRect.height); nsAutoString shouldDisplay, menuActive; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, menuActive); diff --git a/mozilla/layout/xul/base/src/nsObeliskLayout.cpp b/mozilla/layout/xul/base/src/nsObeliskLayout.cpp index c7deb6dca97..e2ff7c5ec91 100644 --- a/mozilla/layout/xul/base/src/nsObeliskLayout.cpp +++ b/mozilla/layout/xul/base/src/nsObeliskLayout.cpp @@ -221,77 +221,9 @@ nsObeliskLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxS nsBoxSize* last = nsnull; temple->BuildBoxSizeList(aTempleBox, aState, first, last); aBoxSizes = first; - }/* else { */ - nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aComputedBoxSizes, aMinSize, aMaxSize, aFlexes); - // return; - // } - - /* - aMinSize = 0; - aMaxSize = NS_INTRINSICSIZE; - - PRBool isHorizontal = PR_FALSE; - aBox->GetOrientation(isHorizontal); - aFlexes = 0; - - nsIBox* child = nsnull; - aBox->GetChildBox(&child); - - if (child && !aBoxSizes) - aBoxSizes = new (aState) nsBoxSize(); - - nsBoxSize* childSize = aBoxSizes; - - while(child) - { - nscoord flex = 0; - child->GetFlex(aState, flex); - - if (flex > 0) - aFlexes++; - - nsSize pref(0,0); - nsSize min(0,0); - nsSize max(0,0); - - nscoord ascent = 0; - child->GetPrefSize(aState, pref); - child->GetAscent(aState, ascent); - nsMargin margin; - child->GetMargin(margin); - child->GetMinSize(aState, min); - child->GetMaxSize(aState, max); - nsBox::BoundsCheck(min, pref, max); - - AddMargin(child, pref); - AddMargin(child, min); - AddMargin(child, max); - - if (!isHorizontal) { - if (min.width > aMinSize) - aMinSize = min.width; - - if (max.width < aMaxSize) - aMaxSize = max.width; - - } else { - if (min.height > aMinSize) - aMinSize = min.height; - - if (max.height < aMaxSize) - aMaxSize = max.height; - } - - - child->GetNextBox(&child); - if (child && !childSize->next) - { - childSize->next = new (aState) nsBoxSize(); - childSize = childSize->next; - } } - */ + nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aComputedBoxSizes, aMinSize, aMaxSize, aFlexes); } void diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp index 9e95f01ec08..93b2d551b25 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp @@ -51,6 +51,7 @@ #include "nsISupportsArray.h" #include "nsIDOMText.h" #include "nsBoxLayoutState.h" +#include "nsIScrollableFrame.h" #define NS_MENU_POPUP_LIST_INDEX (NS_AREA_FRAME_ABSOLUTE_LIST_INDEX + 1) @@ -97,7 +98,10 @@ NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) // nsPopupSetFrame cntr // nsPopupSetFrame::nsPopupSetFrame(nsIPresShell* aShell):nsBoxFrame(aShell), -mPresContext(nsnull), mElementFrame(nsnull), mCreateHandlerSucceeded(PR_FALSE) +mPresContext(nsnull), +mElementFrame(nsnull), +mCreateHandlerSucceeded(PR_FALSE), +mLastPref(-1,-1) { } // cntr @@ -223,16 +227,61 @@ nsPopupSetFrame::Layout(nsBoxLayoutState& aState) BoundsCheck(minSize, prefSize, maxSize); - AddMargin(ibox, prefSize); + // if the pref size changed then set bounds to be the pref size + // and sync the view. And set new pref size. + if (mLastPref != prefSize) { + ibox->SetBounds(aState, nsRect(0,0,prefSize.width, prefSize.height)); + RePositionPopup(aState); + mLastPref = prefSize; + } - // lay it out - LayoutChildAt(aState, ibox, nsRect(0,0,prefSize.width, prefSize.height)); + // is the new size too small? Make sure we handle scrollbars correctly + nsIBox* child; + ibox->GetChildBox(&child); + + nsRect bounds(0,0,0,0); + ibox->GetBounds(bounds); + + nsCOMPtr scrollframe = do_QueryInterface(child); + if (scrollframe) { + nsIScrollableFrame::nsScrollPref pref; + scrollframe->GetScrollPreference(&pref); + + if (pref == nsIScrollableFrame::Auto) + { + // if our pref height + if (bounds.height < prefSize.height) { + // layout the child + ibox->Layout(aState); + + nscoord width; + nscoord height; + scrollframe->GetScrollbarSizes(aState.GetPresContext(), &width, &height); + if (bounds.width < prefSize.width + width) + { + bounds.width += width; + //printf("Width=%d\n",width); + ibox->SetBounds(aState, bounds); + } + } + } + } + + // layout the child + ibox->Layout(aState); + + // only size popup if open + if (mCreateHandlerSucceeded) { + nsIView* view = nsnull; + popupChild->GetView(aState.GetPresContext(), &view); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->ResizeView(view, bounds.width, bounds.height); + } } SyncLayout(aState); - LayoutFinished(aState); - return rv; } @@ -275,7 +324,7 @@ nsPopupSetFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDeb void -nsPopupSetFrame::LayoutFinished(nsBoxLayoutState& aState) +nsPopupSetFrame::RePositionPopup(nsBoxLayoutState& aState) { // Sync up the view. nsIFrame* activeChild = GetActiveChild(); @@ -431,6 +480,8 @@ nsPopupSetFrame::DestroyPopup() mCreateHandlerSucceeded = PR_FALSE; mElementFrame = nsnull; mXPos = mYPos = 0; + mLastPref.width = -1; + mLastPref.height = -1; return NS_OK; } @@ -489,6 +540,7 @@ nsPopupSetFrame::OpenPopup(PRBool aActivateFlag) content->GetAttribute(kNameSpaceID_None, nsXULAtoms::ignorekeys, property); if ( !property.EqualsWithConversion("true") && childPopup ) childPopup->InstallKeyboardNavigator(); + } else { if (!OnDestroy()) @@ -517,14 +569,22 @@ nsPopupSetFrame::ActivatePopup(PRBool aActivateFlag) GetActiveChildElement(getter_AddRefs(content)); if (content) { // When we sync the popup view with the frame, we'll show the popup if |menutobedisplayed| - // is set by setting the |menuactive| attribute. This trips CSS to make the view visible. - // We wait until the last possible moment to show to avoid flashing, but we can just go - // ahead and hide it here if we're told to (no additional stages necessary). + // is set by setting the |menuactive| attribute. This used to trip css into showing the menu + // but now we do it ourselves. if (aActivateFlag) content->SetAttribute(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, NS_ConvertASCIItoUCS2("true"), PR_TRUE); else { content->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE); content->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menutobedisplayed, PR_TRUE); + + // make sure we hide the popup. + nsIFrame* activeChild = GetActiveChild(); + nsIView* view = nsnull; + activeChild->GetView(mPresContext, &view); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->SetViewVisibility(view, nsViewVisibility_kHide); + viewManager->ResizeView(view, 0, 0); } } } diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.h b/mozilla/layout/xul/base/src/nsPopupSetFrame.h index af27c13f93e..9222bf57196 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.h +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.h @@ -73,7 +73,7 @@ public: NS_IMETHOD Destroy(nsIPresContext* aPresContext); // Reflow methods - void LayoutFinished(nsBoxLayoutState& aState); + virtual void RePositionPopup(nsBoxLayoutState& aState); NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, @@ -132,7 +132,7 @@ protected: PRInt32 mYPos; // Active child's y position nsAutoString mPopupType; PRBool mCreateHandlerSucceeded; // Did the create handler succeed? - + nsSize mLastPref; }; // class nsPopupSetFrame #endif diff --git a/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp b/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp index cb3f5ac6400..be7588085fc 100644 --- a/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsRootBoxFrame.cpp @@ -50,13 +50,8 @@ static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID); static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); -/** - * Root frame class. - * - * The root frame is the parent frame for the document element's frame. - * It only supports having a single child frame which must be an area - * frame - */ +//#define DEBUG_REFLOW + class nsRootBoxFrame : public nsBoxFrame { public: @@ -196,6 +191,10 @@ nsRootBoxFrame::RemoveFrame(nsIPresContext* aPresContext, return rv; } +#ifdef DEBUG_REFLOW +PRInt32 gReflows = 0; +#endif + NS_IMETHODIMP nsRootBoxFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -203,6 +202,11 @@ nsRootBoxFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame", aReflowState.reason); + +#ifdef DEBUG_REFLOW + gReflows++; + printf("----Reflow %d----\n", gReflows); +#endif return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp index 5e3a54347df..6431001ce2f 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp @@ -123,6 +123,7 @@ NS_IMETHODIMP_(void) nsScrollbarButtonFrame::Notify(nsITimer *timer) void nsScrollbarButtonFrame::MouseClicked(nsIPresContext* aPresContext) { + nsButtonBoxFrame::MouseClicked(aPresContext); //MouseClicked(); } diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.cpp b/mozilla/layout/xul/base/src/nsSliderFrame.cpp index 6d40b8e7414..2925d1a4504 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSliderFrame.cpp @@ -356,6 +356,8 @@ nsSliderFrame::Layout(nsBoxLayoutState& aState) else thumbRect.y += pos; + nsRect oldThumbRect; + thumbBox->GetBounds(oldThumbRect); LayoutChildAt(aState, thumbBox, thumbRect); SyncLayout(aState); @@ -366,6 +368,10 @@ nsSliderFrame::Layout(nsBoxLayoutState& aState) printf("Current=%d, max=%d\n",c,m); } + // redraw only if thumb changed size. + if (oldThumbRect != thumbRect) + Redraw(aState); + return NS_OK; } @@ -626,6 +632,9 @@ NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + if (isDraggingThumb(aPresContext)) { // XXX I assume it's better not to test for visibility here. diff --git a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp index 5cb63d9187a..fbba2c87f4c 100644 --- a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp @@ -444,6 +444,9 @@ NS_IMETHODIMP nsSplitterFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + // if the mouse is captured always return us as the frame. if (mInner->IsMouseCaptured(aPresContext)) { @@ -819,6 +822,7 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) mChildInfosBefore[mChildInfosBeforeCount].current = isHorizontal ? r.width : r.height; mChildInfosBefore[mChildInfosBeforeCount].flex = flex; mChildInfosBefore[mChildInfosBeforeCount].index = count; + mChildInfosBefore[mChildInfosBeforeCount].changed = mChildInfosBefore[mChildInfosBeforeCount].current; mChildInfosBeforeCount++; } else if (count > childIndex) { mChildInfosAfter[mChildInfosAfterCount].child = childBox; @@ -827,6 +831,7 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) mChildInfosAfter[mChildInfosAfterCount].current = isHorizontal ? r.width : r.height; mChildInfosAfter[mChildInfosAfterCount].flex = flex; mChildInfosAfter[mChildInfosAfterCount].index = count; + mChildInfosAfter[mChildInfosAfterCount].changed = mChildInfosAfter[mChildInfosAfterCount].current; mChildInfosAfterCount++; } } diff --git a/mozilla/layout/xul/base/src/nsSpringFrame.cpp b/mozilla/layout/xul/base/src/nsSpringFrame.cpp index b84aeb2c2ba..6acff410a14 100644 --- a/mozilla/layout/xul/base/src/nsSpringFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSpringFrame.cpp @@ -51,6 +51,10 @@ NS_IMETHODIMP nsSpringFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer, nsIFrame** aFrame) { + + if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) + return NS_ERROR_FAILURE; + if (!mRect.Contains(aPoint)) return NS_ERROR_FAILURE; diff --git a/mozilla/layout/xul/base/src/nsSprocketLayout.cpp b/mozilla/layout/xul/base/src/nsSprocketLayout.cpp index 2b4163c3f42..7c8078f1091 100644 --- a/mozilla/layout/xul/base/src/nsSprocketLayout.cpp +++ b/mozilla/layout/xul/base/src/nsSprocketLayout.cpp @@ -926,7 +926,7 @@ nsSprocketLayout::ComputeChildSizes(nsIBox* aBox, // ----- calculate the springs constants and the size remaining ----- - if (aBoxSizes && !aComputedBoxSizes) + if (!aComputedBoxSizes) aComputedBoxSizes = new (aState) nsComputedBoxSize(); nsBoxSize* boxSizes = aBoxSizes; @@ -934,39 +934,37 @@ nsSprocketLayout::ComputeChildSizes(nsIBox* aBox, PRInt32 count = 0; PRInt32 validCount = 0; - while (boxSizes || computedBoxSizes) + while (boxSizes) { - NS_ASSERTION(!boxSizes || (boxSizes->min <= boxSizes->pref && boxSizes->pref <= boxSizes->max),"bad pref, min, max size"); + NS_ASSERTION((boxSizes->min <= boxSizes->pref && boxSizes->pref <= boxSizes->max),"bad pref, min, max size"); // ignore collapsed children - if (boxSizes && boxSizes->collapsed) + if (boxSizes->collapsed) { computedBoxSizes->valid = PR_TRUE; computedBoxSizes->size = boxSizes->pref; validCount++; } else { - if (computedBoxSizes && computedBoxSizes->valid) { + if (computedBoxSizes->valid) { sizeRemaining -= computedBoxSizes->size; validCount++; } else { - if (boxSizes && computedBoxSizes) { - if (boxSizes->flex == 0) - { - computedBoxSizes->valid = PR_TRUE; - computedBoxSizes->size = boxSizes->pref; - validCount++; - } + if (boxSizes->flex == 0) + { + computedBoxSizes->valid = PR_TRUE; + computedBoxSizes->size = boxSizes->pref; + validCount++; + } - springConstantsRemaining += boxSizes->flex; - sizeRemaining -= boxSizes->pref; - } + springConstantsRemaining += boxSizes->flex; + sizeRemaining -= boxSizes->pref; } } boxSizes = boxSizes->next; - if (boxSizes && !computedBoxSizes->next) + if (!computedBoxSizes->next) computedBoxSizes->next = new (aState) nsComputedBoxSize(); computedBoxSizes = computedBoxSizes->next; @@ -985,44 +983,35 @@ nsSprocketLayout::ComputeChildSizes(nsIBox* aBox, boxSizes = aBoxSizes; computedBoxSizes = aComputedBoxSizes; - while (boxSizes || computedBoxSizes) { + while (boxSizes) { // ignore collapsed springs - if (!(boxSizes && boxSizes->collapsed)) { + if (!boxSizes->collapsed) { nscoord pref = 0; nscoord max = NS_INTRINSICSIZE; nscoord min = 0; nscoord flex = 0; - if (boxSizes) - { - pref = boxSizes->pref; - min = boxSizes->min; - max = boxSizes->max; - flex = boxSizes->flex; - } + pref = boxSizes->pref; + min = boxSizes->min; + max = boxSizes->max; + flex = boxSizes->flex; // ----- look at our min and max limits make sure we aren't too small or too big ----- - if (!(computedBoxSizes && computedBoxSizes->valid)) { + if (!computedBoxSizes->valid) { PRInt32 newSize = pref + (sizeRemaining*flex/springConstantsRemaining); if (newSize<=min) { - - if (computedBoxSizes) { - computedBoxSizes->size = min; - computedBoxSizes->valid = PR_TRUE; - } - + computedBoxSizes->size = min; + computedBoxSizes->valid = PR_TRUE; springConstantsRemaining -= flex; sizeRemaining += pref; sizeRemaining -= min; limit = PR_TRUE; } else if (newSize>=max) { - if (computedBoxSizes) { - computedBoxSizes->size = max; - computedBoxSizes->valid = PR_TRUE; - } + computedBoxSizes->size = max; + computedBoxSizes->valid = PR_TRUE; springConstantsRemaining -= flex; sizeRemaining += pref; sizeRemaining -= max; @@ -1042,26 +1031,22 @@ nsSprocketLayout::ComputeChildSizes(nsIBox* aBox, boxSizes = aBoxSizes; computedBoxSizes = aComputedBoxSizes; - while (boxSizes || computedBoxSizes) { + while (boxSizes) { // ignore collapsed springs if (!(boxSizes && boxSizes->collapsed)) { nscoord pref = 0; nscoord flex = 0; - if (boxSizes) { - pref = boxSizes->pref; - flex = boxSizes->flex; + pref = boxSizes->pref; + flex = boxSizes->flex; + + if (!computedBoxSizes->valid) { + computedBoxSizes->size = pref + flex*sizeRemaining/springConstantsRemaining; + computedBoxSizes->valid = PR_TRUE; } - if (computedBoxSizes) { - if (!computedBoxSizes->valid) { - computedBoxSizes->size = pref + flex*sizeRemaining/springConstantsRemaining; - computedBoxSizes->valid = PR_TRUE; - } - - aGivenSize += computedBoxSizes->size; - } + aGivenSize += computedBoxSizes->size; } boxSizes = boxSizes->next; diff --git a/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp b/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp index d2f61332562..5ba5c4f248b 100644 --- a/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTextBoxFrame.cpp @@ -581,7 +581,12 @@ nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) { nsSize size; nsIPresContext* presContext = aBoxLayoutState.GetPresContext(); - nsIRenderingContext* rendContext = aBoxLayoutState.GetReflowState()->rendContext; + const nsHTMLReflowState* rstate = aBoxLayoutState.GetReflowState(); + if (!rstate) + return; + + nsIRenderingContext* rendContext =rstate->rendContext; + if (rendContext) { GetTextSize(presContext, *rendContext, mTitle, size, mAscent); diff --git a/mozilla/xpfe/global/resources/skin/xul.css b/mozilla/xpfe/global/resources/skin/xul.css index 3a39c834a9e..bd7e233c7db 100644 --- a/mozilla/xpfe/global/resources/skin/xul.css +++ b/mozilla/xpfe/global/resources/skin/xul.css @@ -156,12 +156,12 @@ menuitem.menuitem-non-iconic menupopup { - /*behavior: url("resource:/chrome/xulBindings.xml#popups");*/ + behavior: url("resource:/chrome/xulBindings.xml#popups"); display : none; } popup { - /*behavior: url("resource:/chrome/xulBindings.xml#popups");*/ + behavior: url("resource:/chrome/xulBindings.xml#popups"); display: none; } @@ -174,18 +174,9 @@ popup[menugenerated="true"] { } menupopup, popup { - visibility: hidden; z-index: 2147483647; } -menupopup[menuactive="true"] { - visibility: visible; -} - -popup[menuactive="true"] { - visibility: visible; -} - /******** Titled buttons **********/ /******** Tree widget **********/ @@ -305,10 +296,11 @@ button.bottom { behavior: url(resource:/chrome/xulBindings.xml#buttonbottom); } -separator { +menuseparator, separator { behavior: url(resource:/chrome/xulBindings.xml#separator); } + /* appending to end so we don't make hyatt cry */ progressmeter { behavior: url(resource:/chrome/xulBindings.xml#progressmeter);