diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index ae17e467e22..61807886a1a 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -110,6 +110,7 @@ #include "nsAutoPtr.h" #include "nsXULAtoms.h" #include "nsBoxFrame.h" +#include "nsScrollBoxFrame.h" #include "nsIBoxLayout.h" #ifdef MOZ_ENABLE_CAIRO #include "nsCanvasFrame.h" @@ -322,6 +323,9 @@ NS_NewMenuPopupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); +nsresult +NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + nsresult NS_NewMenuFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags ); @@ -4171,6 +4175,9 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState, ^ | + ScrollBox + + ^ | AreaFrame or BoxFrame (InitialContainingBlock) @@ -4184,15 +4191,18 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState, // ----- reattach gfx scrollbars ------ // Gfx scrollframes were created in the root frame but the primary frame map may have been destroyed if a // new style sheet was loaded so lets reattach the frames to their content. - // XXX this seems truly bogus, we wipe out mGfxScrollFrame below if (mGfxScrollFrame) { - nsIFrame* gfxScrollbarFrame1 = mGfxScrollFrame->GetFirstChild(nsnull); + nsIFrame* scrollBox = mGfxScrollFrame->GetFirstChild(nsnull); + + nsIFrame* gfxScrollbarFrame1 = nsnull; + nsIFrame* gfxScrollbarFrame2 = nsnull; + gfxScrollbarFrame1 = scrollBox->GetNextSibling(); if (gfxScrollbarFrame1) { // XXX This works, but why? aState.mFrameManager-> SetPrimaryFrameFor(gfxScrollbarFrame1->GetContent(), gfxScrollbarFrame1); - nsIFrame* gfxScrollbarFrame2 = gfxScrollbarFrame1->GetNextSibling(); + gfxScrollbarFrame2 = gfxScrollbarFrame1->GetNextSibling(); if (gfxScrollbarFrame2) { // XXX This works, but why? aState.mFrameManager-> @@ -4250,6 +4260,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState, // build a scrollframe if (isScrollable) { + nsIFrame* newScrollFrame = nsnull; nsRefPtr newContext; newContext = BeginBuildingScrollFrame( aState, @@ -4259,10 +4270,11 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState, nsnull, nsCSSAnonBoxes::scrolledContent, PR_FALSE, - scrollFrame); + scrollFrame, + newScrollFrame); styleContext = newContext; - aParentFrame = scrollFrame; + aParentFrame = newScrollFrame; } nsIFrame* contentFrame = nsnull; @@ -4400,6 +4412,10 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, | ScrollFrame + ^ + | + ScrollBox <--- RootScrollableView + ^ | RootFrame(DocElementContainingBlock) @@ -4490,6 +4506,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, // will act as the scrolling mechanism for the viewport. // XXX Do we even need a viewport when printing to a printer? + //isScrollable = PR_FALSE; + // As long as the webshell doesn't prohibit it, and the device supports // it, create a scroll frame that will act as the scolling mechanism for // the viewport. @@ -4517,6 +4535,31 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, isScrollable = PR_FALSE; } + // Don't create a scrollframe when we're inside a frame or iframe with + // scrolling="no". This makes the frame hierarchy inconsistent and is + // unnecessary for correctness (since + // nsGfxScrollFrameInner::GetScrollbarStyles handles all the necessary + // cases), but it seems to be needed for performance. + if (isScrollable) { + nsresult rv; + if (presContext) { + nsCOMPtr container = presContext->GetContainer(); + if (container) { + nsCOMPtr scrollableContainer = do_QueryInterface(container, &rv); + if (NS_SUCCEEDED(rv) && scrollableContainer) { + PRInt32 scrolling = -1; + scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,&scrolling); + if (nsIScrollable::Scrollbar_Never == scrolling) { + scrollableContainer->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,&scrolling); + if (nsIScrollable::Scrollbar_Never == scrolling) { + isScrollable = PR_FALSE; + } + } + } + } + } + } + if (isPaginated) { if (isPrintPreview) { isScrollable = presContext->HasPaginatedScrolling(); @@ -4540,11 +4583,12 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, nsIFrame* parentFrame = viewportFrame; // If paginated, make sure we don't put scrollbars in - if (!isScrollable) { + if (isPaginated && !isPrintPreview) rootPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull, rootPseudo, viewportPseudoStyle); - } else { + else if (isScrollable) { + // Build the frame. We give it the content we are wrapping which is the document, // the root frame, the parent view port frame, and we should get back the new // frame and the scrollable view if one was created. @@ -4562,6 +4606,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, // scroll style to 'hidden' --- dynamic style changes might put // scrollbars back on the viewport and we don't want to have to // reframe the viewport to create the scrollbar content. + nsIFrame* newScrollableFrame = nsnull; + newFrame = nsnull; rootPseudoStyle = BeginBuildingScrollFrame( state, aDocElement, @@ -4570,19 +4616,61 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIContent* aDocElement, nsnull, rootPseudo, PR_TRUE, - newFrame); + newFrame, + newScrollableFrame); - nsIScrollableFrame* scrollable; - CallQueryInterface(newFrame, &scrollable); - NS_ENSURE_TRUE(scrollable, NS_ERROR_FAILURE); + // Inform the view manager about the root scrollable view + nsIView* view = newScrollableFrame->GetView(); + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); - nsIScrollableView* scrollableView = scrollable->GetScrollableView(); + nsIScrollableView* scrollableView = view->ToScrollableView(); NS_ENSURE_TRUE(scrollableView, NS_ERROR_FAILURE); viewManager->SetRootScrollableView(scrollableView); - parentFrame = newFrame; + parentFrame = newScrollableFrame; mGfxScrollFrame = newFrame; + + } else { + // If no scrollbars and xul, don't build a scrollframe at all. + if (isXUL) { + rootPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull, + rootPseudo, + viewportPseudoStyle); + } else { + // if HTML the always create a scrollframe so anchors work. That way you can scroll to + // anchors even if we don't have scrollbars. + + // create a style context for the scrollport of the viewport + nsRefPtr scrollPseudoStyle; + scrollPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull, + nsCSSAnonBoxes::scrolledContent, + viewportPseudoStyle); + + // create scrollframe + nsIFrame* scrollFrame = nsnull; + NS_NewScrollBoxFrame(mPresShell, &scrollFrame); + NS_ENSURE_TRUE(scrollFrame, NS_ERROR_FAILURE); + + scrollFrame->Init(presContext, nsnull, parentFrame, scrollPseudoStyle, nsnull); + + // resolve a new style for the root frame + rootPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull, + rootPseudo, + scrollPseudoStyle); + + // Inform the view manager about the root scrollable view + nsIView* view = scrollFrame->GetView(); + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); + + nsIScrollableView* scrollableView = view->ToScrollableView(); + NS_ENSURE_TRUE(scrollableView, NS_ERROR_FAILURE); + + viewManager->SetRootScrollableView(scrollableView); + + parentFrame = scrollFrame; + newFrame = scrollFrame; + } } @@ -6197,7 +6285,8 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, nsIFrame* aContentParentFrame, nsIAtom* aScrolledPseudo, PRBool aIsRoot, - nsIFrame*& aNewFrame) + nsIFrame*& aNewFrame, + nsIFrame*& aScrollableFrame) { // Check to see the type of parent frame so we know whether we need to // turn off/on scaling for the scrollbars @@ -6215,6 +6304,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, } } + nsIFrame* scrollFrame = nsnull; nsIFrame* parentFrame = nsnull; nsIFrame* gfxScrollFrame = aNewFrame; @@ -6223,9 +6313,9 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, nsRefPtr contentStyle = aContentStyle; if (!gfxScrollFrame) { - // Build a XULScrollFrame when the child is a box, otherwise an - // HTMLScrollFrame - if (IsXULDisplayType(aContentStyle->GetStyleDisplay())) { + // Build a XULScrollFrame when the parent is a box, because XULScrollFrames + // do box layout well. Otherwise build an HTMLScrollFrame. + if (aParentFrame->IsBoxFrame()) { NS_NewXULScrollFrame(mPresShell, &gfxScrollFrame, aIsRoot); } else { NS_NewHTMLScrollFrame(mPresShell, &gfxScrollFrame, aIsRoot); @@ -6239,11 +6329,11 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, aContentParentFrame, PR_FALSE); } - // if there are any anonymous children for the scroll frame, create - // frames for them. - CreateAnonymousFrames(aState, aContent, mDocument, gfxScrollFrame, PR_FALSE, - PR_FALSE, anonymousItems, nsnull, nsnull, PR_FALSE); + InitGfxScrollFrame(aState, aContent, mDocument, + aParentFrame, aContentParentFrame, contentStyle, + aIsRoot, gfxScrollFrame, anonymousItems); + scrollFrame = anonymousItems.childList; // get the scrollport from the anonymous list parentFrame = gfxScrollFrame; aNewFrame = gfxScrollFrame; @@ -6256,15 +6346,23 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, contentStyle); contentStyle = scrollPseudoStyle; + InitAndRestoreFrame(aState, aContent, parentFrame, contentStyle, nsnull, + scrollFrame); + nsStyleContext* aScrolledChildStyle = styleSet->ResolvePseudoStyleFor(aContent, aScrolledPseudo, contentStyle).get(); + aScrollableFrame = scrollFrame; + + // set the child frame for the gfxscrollbar if the is one. This frames will be the + // 2 scrollbars and the scrolled frame. if (gfxScrollFrame) { gfxScrollFrame->SetInitialChildList(aState.mPresContext, nsnull, anonymousItems.childList); } + if (isPrintPreview && noScalingOfTwips) { aState.mPresContext->SetScalingOfTwips(PR_TRUE); } @@ -6276,24 +6374,14 @@ void nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame, nsIFrame* aScrolledFrame) { - aScrollFrame->AppendFrames(nsnull, aScrolledFrame); - - // force the scrolled frame to have a view + // create a view + // XXXbz should we be passing in a non-null aContentParentFrame? nsHTMLContainerFrame::CreateViewForFrame(aScrolledFrame, nsnull, PR_TRUE); - nsIView* view = aScrolledFrame->GetView(); - if (!view) - return; - // reparent the view from the scrollframe's view to its inner scrolling view - nsIScrollableFrame* scrollable; - CallQueryInterface(aScrollFrame, &scrollable); - if (scrollable) { - nsIViewManager* vm = view->GetViewManager(); - vm->RemoveChild(view); - vm->InsertChild(scrollable->GetScrollableView()->View(), view, nsnull, PR_TRUE); - } + // the the scroll frames child list + aScrollFrame->SetInitialChildList(aScrollFrame->GetPresContext(), nsnull, aScrolledFrame); } - + /** * Called to wrap a gfx scrollframe around a frame. The hierarchy will look like this @@ -6304,13 +6392,18 @@ nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame, * ScrollFrame * ^ * | + * ScrollBox + * ^ + * | * Frame (scrolled frame you passed in) * * *----------------------------------- * LEGEND: * - * ScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars. + * GfxScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars. + * + * ScrollBox: This clips and scrolls its children with a native scrolling window. * * @param aContent the content node of the child to wrap. * @param aScrolledFrame The frame of the content to wrap. This should not be @@ -6336,15 +6429,25 @@ nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState, nsIFrame*& aNewFrame, nsStyleContext*& aScrolledContentStyle) { - nsRefPtr scrolledContentStyle = - BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame, - aContentParentFrame, nsCSSAnonBoxes::scrolledContent, - PR_FALSE, aNewFrame); + nsIFrame *scrollFrame; + + nsRefPtr scrolledContentStyle; + - InitAndRestoreFrame(aState, aContent, aNewFrame, scrolledContentStyle, + scrolledContentStyle = BeginBuildingScrollFrame(aState, + aContent, + aContentStyle, + aParentFrame, + aContentParentFrame, + nsCSSAnonBoxes::scrolledContent, + PR_FALSE, + aNewFrame, + scrollFrame); + + InitAndRestoreFrame(aState, aContent, scrollFrame, scrolledContentStyle, nsnull, aScrolledFrame); - FinishBuildingScrollFrame(aNewFrame, aScrolledFrame); + FinishBuildingScrollFrame(scrollFrame, aScrolledFrame); aScrolledContentStyle = scrolledContentStyle; @@ -6354,6 +6457,34 @@ nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState, } +/** + * If we are building GFX scrollframes this will create one + * if aNewFrame gets a frame passed in, we'll use it instead + * of creating a new frame + */ +nsresult +nsCSSFrameConstructor::InitGfxScrollFrame(nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames) +{ + nsIFrame* scrollBox; + NS_NewScrollBoxFrame(mPresShell, &scrollBox); + + aAnonymousFrames.AddChild(scrollBox); + + // if there are any anonymous children for the scroll frame, create frames for them. + CreateAnonymousFrames(aState, aContent, aDocument, aNewFrame, PR_FALSE, + PR_FALSE, aAnonymousFrames, nsnull, nsnull, PR_FALSE); + + return NS_OK; +} + nsresult nsCSSFrameConstructor::ConstructFrameByDisplayType(nsFrameConstructorState& aState, const nsStyleDisplay* aDisplay, @@ -6402,12 +6533,14 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsFrameConstructorState& aSta ProcessPseudoFrames(aState, aFrameItems); } + nsIFrame *scrollFrame; nsRefPtr scrolledContentStyle = BeginBuildingScrollFrame(aState, aContent, aStyleContext, aState.GetGeometricParent(aDisplay, aParentFrame), aParentFrame, nsCSSAnonBoxes::scrolledContent, - PR_FALSE, newFrame); + PR_FALSE, + newFrame, scrollFrame); // Initialize it nsIFrame* scrolledFrame = nsnull; @@ -6416,11 +6549,11 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsFrameConstructorState& aSta nsFrameItems blockItem; rv = ConstructBlock(aState, scrolledContentStyle->GetStyleDisplay(), aContent, - newFrame, newFrame, scrolledContentStyle, + scrollFrame, scrollFrame, scrolledContentStyle, &scrolledFrame, blockItem, aDisplay->IsPositioned()); NS_ASSERTION(blockItem.childList == scrolledFrame, "Scrollframe's frameItems should be exactly the scrolled frame"); - FinishBuildingScrollFrame(newFrame, scrolledFrame); + FinishBuildingScrollFrame(scrollFrame, scrolledFrame); rv = aState.AddChild(newFrame, aFrameItems, aDisplay, aContent, aStyleContext, aParentFrame); @@ -7673,6 +7806,7 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchy() // // (HTML) // nsHTMLScrollFrame(html)< + // nsScrollBoxFrame(html)< // Canvas(-1)< // Area(html)< // (etc.) @@ -7680,6 +7814,7 @@ nsCSSFrameConstructor::ReconstructDocElementHierarchy() // (XUL #1) // RootBoxFrame(window)< // nsXULScrollFrame< + // nsScrollBoxFrame(window)< // (etc.) // // (XUL #2) diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index 2a8dc622cf6..5b4e54fea0c 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -671,7 +671,8 @@ private: nsIFrame* aContentParentFrame, nsIAtom* aScrolledPseudo, PRBool aIsRoot, - nsIFrame*& aNewFrame); + nsIFrame*& aNewFrame, + nsIFrame*& aScrollableFrame); // Completes the building of the scrollframe: // Creates a view for the scrolledframe and makes it the child of the scrollframe. @@ -679,6 +680,20 @@ private: FinishBuildingScrollFrame(nsIFrame* aScrollFrame, nsIFrame* aScrolledFrame); + // Creates a new GfxScrollFrame, Initializes it, and creates a scroll port for it + // + nsresult + InitGfxScrollFrame(nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames); + + // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false nsresult InitializeSelectFrame(nsFrameConstructorState& aState, diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp index a8902db7ce5..885f0957551 100644 --- a/mozilla/layout/base/nsLayoutUtils.cpp +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -355,6 +355,10 @@ nsLayoutUtils::GetScrollableFrameFor(nsIFrame *aScrolledFrame) if (!frame) { return nsnull; } + frame = frame->GetParent(); + if (!frame) { + return nsnull; + } nsIScrollableFrame *sf; CallQueryInterface(frame, &sf); return sf; @@ -364,8 +368,8 @@ nsLayoutUtils::GetScrollableFrameFor(nsIFrame *aScrolledFrame) nsIScrollableFrame* nsLayoutUtils::GetScrollableFrameFor(nsIScrollableView *aScrollableView) { - nsIFrame *frame = GetFrameFor(aScrollableView->View()->GetParent()); - if (frame) { + nsIFrame *frame = GetFrameFor(aScrollableView->View()); + if (frame && ((frame = frame->GetParent()))) { nsIScrollableFrame *sf; CallQueryInterface(frame, &sf); return sf; @@ -412,7 +416,7 @@ nsLayoutUtils::GetNearestScrollingView(nsIView* aView, Direction aDirection) nscoord totalWidth, totalHeight; scrollableView->GetContainerSize(&totalWidth, &totalHeight); // Get size of currently visible area - nsSize visibleSize = aView->GetBounds().Size(); + nsSize visibleSize = GetFrameFor(aView)->GetSize(); // aDirection can be eHorizontal, eVertical, or eEither // If scrolling in a specific direction, require visible scrollbars or // something to scroll to in that direction. diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index df0982a6cdd..825b476a636 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -432,25 +432,70 @@ nsContainerFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) void nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame) { - nsIFrame* parentFrame = aKidFrame->GetParent(); - if (!aKidFrame->HasView() || !parentFrame) - return; + if (aKidFrame->HasView()) { + nsIView* view = aKidFrame->GetView(); + // Position view relative to its parent, not relative to aKidFrame's + // frame which may not have a view + nsIView* parentView = view->GetParent(); - nsIView* view = aKidFrame->GetView(); - nsIViewManager* vm = view->GetViewManager(); - nsPoint pt; - nsIView* ancestorView = parentFrame->GetClosestView(&pt); + nsIView* containingView; + nsPoint origin; + aKidFrame->GetOffsetFromView(origin, &containingView); - if (ancestorView != view->GetParent()) { - NS_ASSERTION(ancestorView == view->GetParent()->GetParent(), - "Allowed only one anonymous view between frames"); - // parentFrame is responsible for positioning aKidFrame's view - // explicitly - return; + nsIViewManager* vm = view->GetViewManager(); + + // it's possible for the parentView to be nonnull but containingView to be + // null, when the parent view doesn't belong to this frame tree but to + // the frame tree of some enclosing document. We do nothing in that case, + // but we have to check that containingView is nonnull or we will crash. + if (nsnull != containingView && containingView != parentView) { + NS_ERROR("This hack should not be needed now!!! See bug 126263."); + + // XXX roc this should be no longer needed, but it still is for printing/print preview + + // it is possible for parent view not to have a frame attached to it + // kind of an anonymous view. This happens with native scrollbars and + // the clip view. To fix this we need to go up and parentView chain + // until we find a view with client data. This is total HACK to fix + // the HACK below. COMBO box code should NOT be in the container code!!! + // And the case it looks from does not just happen for combo boxes. Native + // scrollframes get in this situation too!! + while (parentView) { + void *data = parentView->GetClientData(); + if (data) + break; + + origin -= parentView->GetPosition(); + parentView = parentView->GetParent(); + } + + if (containingView != parentView) + { + // Huh, the view's parent view isn't the same as the containing view. + // This happens for combo box drop-down frames. + // + // We have the origin in the coordinate space of the containing view, + // but we need it in the coordinate space of the parent view so do a + // view translation + origin += containingView->GetOffsetTo(parentView); + } + } + + if (parentView) { + // If the parent view is scrollable, then adjust the origin by + // the parent's scroll position. + nsIScrollableView* scrollable = parentView->ToScrollableView(); + if (scrollable) { + nscoord scrollX = 0, scrollY = 0; + scrollable->GetScrollPosition(scrollX, scrollY); + + origin.x -= scrollX; + origin.y -= scrollY; + } + } + + vm->MoveViewTo(view, origin.x, origin.y); } - - pt += aKidFrame->GetPosition(); - vm->MoveViewTo(view, pt.x, pt.y); } static PRBool @@ -815,10 +860,6 @@ nsContainerFrame::SyncFrameViewProperties(nsPresContext* aPresContext, PRBool nsContainerFrame::FrameNeedsView(nsIFrame* aFrame) { - if (aFrame->TypeAlwaysNeedsView()) { - return PR_TRUE; - } - nsStyleContext* sc = aFrame->GetStyleContext(); const nsStyleDisplay* display = sc->GetStyleDisplay(); if (display->mOpacity != 1.0f) { @@ -845,6 +886,10 @@ nsContainerFrame::FrameNeedsView(nsIFrame* aFrame) return PR_TRUE; } + if (aFrame->GetType() == nsLayoutAtoms::objectFrame) { + return PR_TRUE; + } + // See if the frame is block-level and has 'overflow' set to // '-moz-hidden-unscrollable'. If so, then we need to give it a view // so clipping of any child views works correctly. Note that if it's diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index 3d38fc53be6..2cb9a6a9e85 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -2031,7 +2031,7 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, nsIView *closestView = closestFrame->GetClosestView(); if (closestView && view != closestView) - newPoint -= closestView->GetOffsetTo(view); + newPoint -= closestView->GetPosition(); // printf(" 0x%.8x 0x%.8x %4d %4d\n", // closestFrame, closestView, closestXDistance, closestYDistance); diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index 92b9a3f147b..49c108bbc94 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -50,6 +50,7 @@ #include "nsHTMLContainerFrame.h" #include "nsWidgetsCID.h" #include "nsGfxScrollFrame.h" +#include "nsScrollBoxFrame.h" #include "nsLayoutAtoms.h" #include "nsXULAtoms.h" #include "nsHTMLAtoms.h" @@ -190,14 +191,13 @@ nsHTMLScrollFrame::Destroy(nsPresContext* aPresContext) } NS_IMETHODIMP -nsHTMLScrollFrame:: -SetInitialChildList(nsPresContext* aPresContext, +nsHTMLScrollFrame::SetInitialChildList(nsPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); - mInner.CreateScrollableView(); + mInner.ReloadChildFrames(); // listen for scroll events. @@ -253,6 +253,25 @@ nsHTMLScrollFrame::GetPadding(nsMargin& aMargin) return NS_OK; } +NS_IMETHODIMP +nsHTMLScrollFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, + const nsPoint& aPoint, + nsIContent ** aNewContent, + PRInt32& aContentOffset, + PRInt32& aContentOffsetEnd, + PRBool& aBeginFrameContent) +{ + //we need to translate the coordinates to the inner + nsIView *view = GetClosestView(); + if (!view) + return NS_ERROR_FAILURE; + + nsIView *innerView = mInner.mScrollAreaBox->GetClosestView(); + nsPoint point = aPoint - innerView->GetOffsetTo(view); + + return mInner.mScrollAreaBox->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); +} + PRIntn nsHTMLScrollFrame::GetSkipSides() const { @@ -269,10 +288,7 @@ NS_IMETHODIMP nsHTMLScrollFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) { aAscent = 0; - if (!mInner.mScrolledFrame) - return NS_OK; - - nsresult rv = mInner.mScrolledFrame->GetAscent(aState, aAscent); + nsresult rv = mInner.mScrollAreaBox->GetAscent(aState, aAscent); nsMargin m(0,0,0,0); GetBorderAndPadding(m); aAscent += m.top; @@ -312,7 +328,7 @@ nsHTMLScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) // // Details: We're going to pass our width (or height) constraint // down to nsBoxToBlockAdaptor. Then when we call - // mScrolledFrame->GetPrefSize below, it will reflow the scrolled + // mScrollAreaBox->GetPrefSize below, it will reflow the scrolled // block with this width (or height) constraint, and report the resulting // height (or width) of the block. So if possible we'll be sized exactly to the // height (or width) of the block, which is what we want because 'overflow' @@ -358,7 +374,7 @@ nsHTMLScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) aState.SetScrolledBlockSizeConstraint(nsSize(-1,-1)); } - nsresult rv = mInner.mScrolledFrame->GetPrefSize(aState, aSize); + nsresult rv = mInner.mScrollAreaBox->GetPrefSize(aState, aSize); // Restore old constraint. aState.SetScrolledBlockSizeConstraint(oldConstrainedSize); @@ -387,7 +403,7 @@ nsHTMLScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) nsBox::AddMargin(mInner.mVScrollbarBox, vSize); } - // Scrolled frames don't have their own margins + nsBox::AddMargin(mInner.mScrollAreaBox, aSize); aSize.width += vSize.width; aSize.height += hSize.height; @@ -406,7 +422,7 @@ nsHTMLScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) PropagateDebug(aState); #endif - aSize = mInner.mScrolledFrame->GetMinSizeForScrollArea(aState); + nsresult rv = mInner.mScrollAreaBox->GetMinSize(aState, aSize); nsGfxScrollFrameInner::ScrollbarStyles styles = GetScrollbarStyles(); @@ -433,7 +449,7 @@ nsHTMLScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) AddBorderAndPadding(aSize); AddInset(aSize); nsIBox::AddCSSMinSize(aState, this, aSize); - return NS_OK; + return rv; } NS_IMETHODIMP @@ -683,7 +699,6 @@ nsXULScrollFrame::SetInitialChildList(nsPresContext* aPresContext, nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); - mInner.CreateScrollableView(); mInner.ReloadChildFrames(); // listen for scroll events. @@ -739,6 +754,25 @@ nsXULScrollFrame::GetPadding(nsMargin& aMargin) return NS_OK; } +NS_IMETHODIMP +nsXULScrollFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, + const nsPoint& aPoint, + nsIContent ** aNewContent, + PRInt32& aContentOffset, + PRInt32& aContentOffsetEnd, + PRBool& aBeginFrameContent) +{ + //we need to translate the coordinates to the inner + nsIView *view = GetClosestView(); + if (!view) + return NS_ERROR_FAILURE; + + nsIView *innerView = mInner.mScrollAreaBox->GetClosestView(); + nsPoint point = aPoint - innerView->GetOffsetTo(view); + + return mInner.mScrollAreaBox->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, aContentOffset, aContentOffsetEnd, aBeginFrameContent); +} + PRIntn nsXULScrollFrame::GetSkipSides() const { @@ -755,10 +789,7 @@ NS_IMETHODIMP nsXULScrollFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent) { aAscent = 0; - if (!mInner.mScrolledFrame) - return NS_OK; - - nsresult rv = mInner.mScrolledFrame->GetAscent(aState, aAscent); + nsresult rv = mInner.mScrollAreaBox->GetAscent(aState, aAscent); nsMargin m(0,0,0,0); GetBorderAndPadding(m); aAscent += m.top; @@ -798,7 +829,7 @@ nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) // // Details: We're going to pass our width (or height) constraint // down to nsBoxToBlockAdaptor. Then when we call - // mScrolledFrame->GetPrefSize below, it will reflow the scrolled + // mScrollAreaBox->GetPrefSize below, it will reflow the scrolled // block with this width (or height) constraint, and report the resulting // height (or width) of the block. So if possible we'll be sized exactly to the // height (or width) of the block, which is what we want because 'overflow' @@ -844,7 +875,7 @@ nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) aState.SetScrolledBlockSizeConstraint(nsSize(-1,-1)); } - nsresult rv = mInner.mScrolledFrame->GetPrefSize(aState, aSize); + nsresult rv = mInner.mScrollAreaBox->GetPrefSize(aState, aSize); // Restore old constraint. aState.SetScrolledBlockSizeConstraint(oldConstrainedSize); @@ -873,7 +904,7 @@ nsXULScrollFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) nsBox::AddMargin(mInner.mVScrollbarBox, vSize); } - // scrolled frames don't have their own margins + nsBox::AddMargin(mInner.mScrollAreaBox, aSize); aSize.width += vSize.width; aSize.height += hSize.height; @@ -892,7 +923,7 @@ nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) PropagateDebug(aState); #endif - aSize = mInner.mScrolledFrame->GetMinSizeForScrollArea(aState); + nsresult rv = mInner.mScrollAreaBox->GetMinSize(aState, aSize); nsGfxScrollFrameInner::ScrollbarStyles styles = GetScrollbarStyles(); @@ -919,7 +950,7 @@ nsXULScrollFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize) AddBorderAndPadding(aSize); AddInset(aSize); nsIBox::AddCSSMinSize(aState, this, aSize); - return NS_OK; + return rv; } NS_IMETHODIMP @@ -1035,10 +1066,9 @@ NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) //-------------------- Inner ---------------------- nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsBoxFrame* aOuter) - : mScrollableView(nsnull), - mHScrollbarBox(nsnull), + : mHScrollbarBox(nsnull), mVScrollbarBox(nsnull), - mScrolledFrame(nsnull), + mScrollAreaBox(nsnull), mScrollCornerBox(nsnull), mOnePixel(20), mOuter(aOuter), @@ -1052,9 +1082,7 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsBoxFrame* aOuter) mHasHorizontalScrollbar(PR_FALSE), mViewInitiatedScroll(PR_FALSE), mFrameInitiatedScroll(PR_FALSE), - mDidHistoryRestore(PR_FALSE), - mHorizontalOverflow(PR_FALSE), - mVerticalOverflow(PR_FALSE) + mDidHistoryRestore(PR_FALSE) { } @@ -1070,74 +1098,6 @@ NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::Release(void) NS_IMPL_QUERY_INTERFACE1(nsGfxScrollFrameInner, nsIScrollPositionListener) -PRBool -nsGfxScrollFrameInner::NeedsClipWidget() const -{ - // Scrollports contained in form controls (e.g., listboxes) don't get - // widgets. - for (nsIFrame* parentFrame = mOuter->GetParent(); parentFrame; - parentFrame = parentFrame->GetParent()) { - nsIFormControlFrame* fcFrame; - if ((NS_SUCCEEDED(parentFrame->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame)))) { - return PR_FALSE; - } - } - - // Scrollports that don't ever show associated scrollbars don't get - // widgets, because they will seldom actually be scrolled. - nsIScrollableFrame *scrollableFrame; - CallQueryInterface(mOuter, &scrollableFrame); - ScrollbarStyles scrollbars = scrollableFrame->GetScrollbarStyles(); - if ((scrollbars.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN - || scrollbars.mHorizontal == NS_STYLE_OVERFLOW_VISIBLE) - && (scrollbars.mVertical == NS_STYLE_OVERFLOW_HIDDEN - || scrollbars.mVertical == NS_STYLE_OVERFLOW_VISIBLE)) { - return PR_FALSE; - } - - return PR_TRUE; -} - -nsresult -nsGfxScrollFrameInner::GetChildContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) -{ - // We need to overrride this to ensure that scrollbars are ignored - - // Since we definitely have a view, aPoint is relative to this frame's view. We - // need to make it relative to the scrolled frame. - nsPoint point = aPoint - mScrollableView->View()->GetOffsetTo(mOuter->GetView()); - - return mScrolledFrame->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, - aContentOffset, aContentOffsetEnd, - aBeginFrameContent); -} - -void -nsGfxScrollFrameInner::CreateScrollableView() -{ - nsIView* outerView = mOuter->GetView(); - NS_ASSERTION(outerView, "scrollframes must have views"); - nsIViewManager* viewManager = outerView->GetViewManager(); - mScrollableView = viewManager->CreateScrollableView(mOuter->GetRect(), outerView); - if (!mScrollableView) - return; - - nsIView* view = mScrollableView->View(); - - // Insert the view into the view hierarchy - viewManager->InsertChild(outerView, view, nsnull, PR_TRUE); - - // Have the scrolling view create its internal widgets - if (NeedsClipWidget()) { - mScrollableView->CreateScrollControls(); - } -} - static void HandleScrollPref(nsIScrollable *aScrollable, PRInt32 aOrientation, PRUint8& aValue) { @@ -1251,49 +1211,50 @@ nsGfxScrollFrameInner::ScrollToRestoredPosition() } } -void -nsGfxScrollFrameInner::PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType) -{ - nsScrollPortEvent* event = new nsScrollPortEvent(aOverflow ? - NS_SCROLLPORT_OVERFLOW : - NS_SCROLLPORT_UNDERFLOW); - event->orient = aType; - mOuter->GetPresContext()->PresShell()->PostDOMEvent(mOuter->GetContent(), event); -} - void nsGfxScrollFrameInner::ReloadChildFrames() { - mScrolledFrame = nsnull; + mScrollAreaBox = nsnull; mHScrollbarBox = nsnull; mVScrollbarBox = nsnull; mScrollCornerBox = nsnull; nsIFrame* frame = mOuter->GetFirstChild(nsnull); while (frame) { - nsIContent* content = frame->GetContent(); - if (content == mOuter->GetContent()) { - NS_ASSERTION(!mScrolledFrame, "Already found the scrolled frame"); - mScrolledFrame = frame; - } else { - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, - nsXULAtoms::orient, value)) { - // probably a scrollbar then - if (value.LowerCaseEqualsLiteral("horizontal")) { - NS_ASSERTION(!mHScrollbarBox, "Found multiple horizontal scrollbars?"); - mHScrollbarBox = frame; - } else { - NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?"); - mVScrollbarBox = frame; - } + PRBool understood = PR_FALSE; + + if (frame->IsBoxFrame()) { + if (frame->GetType() == nsLayoutAtoms::scrollFrame) { + NS_ASSERTION(!mScrollAreaBox, "Found multiple scroll areas?"); + mScrollAreaBox = frame; + understood = PR_TRUE; } else { - // probably a scrollcorner - NS_ASSERTION(!mScrollCornerBox, "Found multiple scrollcorners"); - mScrollCornerBox = frame; + nsIContent* content = frame->GetContent(); + if (content) { + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, + nsXULAtoms::orient, value)) { + // probably a scrollbar then + if (value.LowerCaseEqualsLiteral("horizontal")) { + NS_ASSERTION(!mHScrollbarBox, "Found multiple horizontal scrollbars?"); + mHScrollbarBox = frame; + } else { + NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?"); + mVScrollbarBox = frame; + } + understood = PR_TRUE; + } else { + // probably a scrollcorner + NS_ASSERTION(!mScrollCornerBox, "Found multiple scrollcorners"); + mScrollCornerBox = frame; + understood = PR_TRUE; + } + } } } + NS_ASSERTION(understood, "What is this frame doing here?"); + frame = frame->GetNextSibling(); } } @@ -1505,6 +1466,22 @@ void nsGfxScrollFrameInner::CurPosAttributeChanged(nsIContent* aContent, PRInt32 } } +nsIScrollableView* +nsGfxScrollFrameInner::GetScrollableView() const +{ + if (!mScrollAreaBox) { + return nsnull; + } + + nsIView* view = mScrollAreaBox->GetView(); + if (!view) return nsnull; + + nsIScrollableView* scrollingView = view->ToScrollableView(); + NS_ASSERTION(scrollingView, + "assertion gfx scrollframe does not contain a scrollframe"); + return scrollingView; +} + PRBool nsGfxScrollFrameInner::AddHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop) { @@ -1695,131 +1672,6 @@ nsGfxScrollFrameInner::AdjustReflowStateBack(nsBoxLayoutState& aState, PRBool aS } } -void -nsGfxScrollFrameInner::LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect) -{ - nsIView* scrollView = mScrollableView->View(); - nsIViewManager* vm = scrollView->GetViewManager(); - vm->MoveViewTo(scrollView, aRect.x, aRect.y); - vm->ResizeView(scrollView, nsRect(nsPoint(0, 0), aRect.Size()), PR_TRUE); - - PRUint32 oldflags = aState.LayoutFlags(); - // set the origin of childRect to (0,0) even though we might have borders or - // a left-hand-side scrollbar. We're going to account for that by positioning the - // anonymous mScrollableView. - nsRect childRect = nsRect(nsPoint(0, 0), aRect.Size()); - PRBool isBoxWrapped = mScrolledFrame->IsBoxWrapped(); - - // see if our child is html. If it is then - // never include the overflow. The child will be the size - // given but its view will include the overflow size. - if (isBoxWrapped) - mScrolledFrame->SetIncludeOverflow(PR_FALSE); - - PRInt32 flags = NS_FRAME_NO_MOVE_VIEW; - - // if the child is not a box, then we can't use - // min size. the child technically can get as small as it wants - // to. - if (!isBoxWrapped) { - nsSize min(0,0); - mScrolledFrame->GetMinSize(aState, min); - - if (min.height > childRect.height) - childRect.height = min.height; - - if (min.width > childRect.width) - childRect.width = min.width; - } else { - // don't size the view if our child isn't a box - flags |= NS_FRAME_NO_SIZE_VIEW; - } - - aState.SetLayoutFlags(flags); - mScrolledFrame->SetBounds(aState, childRect); - mScrolledFrame->Layout(aState); - - childRect = mScrolledFrame->GetRect(); - - // now size the view to the size including our overflow. - if (isBoxWrapped) { - nsSize overflow(0,0); - mScrolledFrame->GetOverflow(overflow); - childRect.width = overflow.width; - childRect.height = overflow.height; - } - - if (childRect.width < aRect.width || childRect.height < aRect.height) - { - childRect.width = PR_MAX(childRect.width, aRect.width); - childRect.height = PR_MAX(childRect.height, aRect.height); - - // remove overflow area when we update the bounds, - // because we've already accounted for it - mScrolledFrame->SetBounds(aState, childRect, PR_TRUE); - } - - aState.SetLayoutFlags(oldflags); - - if (isBoxWrapped) { - nsRect r(0, 0, childRect.width, childRect.height); - nsContainerFrame::SyncFrameViewAfterReflow(mScrolledFrame->GetPresContext(), mScrolledFrame, - mScrolledFrame->GetView(), &r, NS_FRAME_NO_MOVE_VIEW); - } - - mScrollableView->ComputeScrollOffsets(PR_TRUE); - - childRect = mScrolledFrame->GetRect(); - - // first see what changed - PRBool vertChanged = PR_FALSE; - PRBool horizChanged = PR_FALSE; - - if (mVerticalOverflow && childRect.height <= aRect.height) { - mVerticalOverflow = PR_FALSE; - vertChanged = PR_TRUE; - } else if (childRect.height > aRect.height) { - // XXX we fire an event every time we reflow with overflowing height. Do - // we really need to? - if (!mVerticalOverflow) { - mVerticalOverflow = PR_TRUE; - } - vertChanged = PR_TRUE; - } - - if (mHorizontalOverflow && childRect.width <= aRect.width) { - mHorizontalOverflow = PR_FALSE; - horizChanged = PR_TRUE; - } else if (childRect.width > aRect.width) { - // XXX we fire an event every time we reflow with overflowing width. Do - // we really need to? - if (!mHorizontalOverflow) { - mHorizontalOverflow = PR_TRUE; - } - horizChanged = PR_TRUE; - } - - // if either changed - if (vertChanged || horizChanged) - { - // are there 2 events or 1? - if (vertChanged && horizChanged) { - if (mVerticalOverflow == mHorizontalOverflow) - { - // both either overflowed or underflowed. 1 event - PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::both); - } else { - // one overflowed and one underflowed - PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::vertical); - PostScrollPortEvent(mHorizontalOverflow, nsScrollPortEvent::horizontal); - } - } else if (vertChanged) // only one changed either vert or horiz - PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::vertical); - else - PostScrollPortEvent(mHorizontalOverflow, nsScrollPortEvent::horizontal); - } -} - /** * Reflow the scroll area if it needs it and return its size. Also determine if the reflow will * cause any of the scrollbars to need to be reflowed. @@ -1905,10 +1757,11 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) if (mHasVerticalScrollbar) AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight); - nsRect oldScrollAreaBounds = mScrollableView->View()->GetBounds(); + nsRect oldScrollAreaBounds; + mScrollAreaBox->GetClientRect(oldScrollAreaBounds); // layout our the scroll area - LayoutScrollArea(aState, scrollAreaRect); + LayoutBox(aState, mScrollAreaBox, scrollAreaRect); // now look at the content area and see if we need scrollbars or not PRBool needsLayout = PR_FALSE; @@ -1944,7 +1797,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) resizeState.SetLayoutReason(nsBoxLayoutState::Resize); PRBool setBack; AdjustReflowStateForPrintPreview(aState, setBack); - LayoutScrollArea(resizeState, scrollAreaRect); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); AdjustReflowStateBack(aState, setBack); needsLayout = PR_FALSE; } @@ -1984,6 +1837,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) if (textControl) { needsLayout = PR_TRUE; reflowState->mRightEdge = scrolledContentSize.width; + mScrollAreaBox->MarkDirty(aState); } } #endif // IBMBIDI @@ -2004,7 +1858,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) resizeState.SetLayoutReason(nsBoxLayoutState::Resize); PRBool setBack; AdjustReflowStateForPrintPreview(aState, setBack); - LayoutScrollArea(resizeState, scrollAreaRect); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); AdjustReflowStateBack(aState, setBack); needsLayout = PR_FALSE; #ifdef IBMBIDI @@ -2110,7 +1964,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState) if (needsLayout) { nsBoxLayoutState resizeState(aState); resizeState.SetLayoutReason(nsBoxLayoutState::Resize); - LayoutScrollArea(resizeState, scrollAreaRect); + LayoutBox(resizeState, mScrollAreaBox, scrollAreaRect); needsLayout = PR_FALSE; } @@ -2212,18 +2066,33 @@ nsGfxScrollFrameInner::SetAttribute(nsIBox* aBox, nsIAtom* aAtom, nscoord aSize, return PR_FALSE; } +/** + * Gets the size of the area that lies inside the scrollbars but clips the scrolled frame + */ nsSize nsGfxScrollFrameInner::GetScrolledSize() const { - nsRect r = mScrolledFrame->GetOverflowRect(); - return nsSize(r.XMost(), r.YMost()); + // our scrolled size is the size of our scrolled view. + nsIBox* child = nsnull; + mScrollAreaBox->GetChildBox(&child); + nsIView* view = child->GetView(); + NS_ASSERTION(view,"Scrolled frame must have a view!!!"); + + nsRect rect = view->GetBounds(); + nsSize size(rect.width, rect.height); + + nsBox::AddMargin(child, size); + nsBox::AddBorderAndPadding(mScrollAreaBox, size); + nsBox::AddInset(mScrollAreaBox, size); + + return size; } nsMargin nsGfxScrollFrameInner::GetActualScrollbarSizes() const { nsRect contentRect; mOuter->GetClientRect(contentRect); - nsRect scrollArea = mScrollableView->View()->GetBounds(); + nsRect scrollArea = mScrollAreaBox->GetRect(); return nsMargin(scrollArea.x - contentRect.x, scrollArea.y - contentRect.y, contentRect.XMost() - scrollArea.XMost(), @@ -2359,6 +2228,7 @@ nsGfxScrollFrameInner::RestoreState(nsPresState* aState) if (scrollingView) { scrollingView->GetScrollPosition(mLastPos.x, mLastPos.y); } else { + // Our scrollboxframe probably hasn't been constructed yet. mLastPos = nsPoint(0, 0); } } diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index b07dbabc6c2..4d2bf33ae51 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -43,7 +43,6 @@ #include "nsIScrollableFrame.h" #include "nsIScrollPositionListener.h" #include "nsIStatefulFrame.h" -#include "nsGUIEvent.h" class nsISupportsArray; class nsIScrollableView; @@ -70,18 +69,8 @@ public: // reload our child frame list. // We need this if a scrollbar frame is recreated. void ReloadChildFrames(); - PRBool NeedsClipWidget() const; - void CreateScrollableView(); void CreateAnonymousContent(nsISupportsArray& aAnonymousChildren); - void PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType); - - nsresult GetChildContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent); // nsIScrollPositionListener @@ -97,38 +86,41 @@ public: nsresult Layout(nsBoxLayoutState& aState); nsresult LayoutBox(nsBoxLayoutState& aState, nsIBox* aBox, const nsRect& aRect); - void LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect); - + // Like ScrollPositionDidChange, but initiated by this frame rather than from the // scrolling view void InternalScrollPositionDidChange(nscoord aX, nscoord aY); - PRBool AddRemoveScrollbar(PRBool& aHasScrollbar, - nscoord& aXY, - nscoord& aSize, - nscoord aSbSize, - PRBool aOnRightOrBottom, - PRBool aAdd); - - 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); - void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); - void RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); + PRBool AddRemoveScrollbar (PRBool& aHasScrollbar, + nscoord& aXY, + nscoord& aSize, + nscoord aSbSize, + PRBool aOnRightOrBottom, + PRBool aAdd); - nsIScrollableView* GetScrollableView() const { return mScrollableView; } + 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); + void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom); + void RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight); + + nsIScrollableView* GetScrollableView() const; void ScrollToRestoredPosition(); nsPresState* SaveState(); void RestoreState(nsPresState* aState); - nsIFrame* GetScrolledFrame() const { return mScrolledFrame; } + nsIFrame* GetScrolledFrame() const { + nsIFrame* childBox; + mScrollAreaBox->GetChildBox(&childBox); + return childBox; + } void ScrollbarChanged(nsPresContext* aPresContext, nscoord aX, nscoord aY, PRUint32 aFlags); @@ -139,10 +131,9 @@ public: void AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, PRBool& aSetBack); void AdjustReflowStateBack(nsBoxLayoutState& aState, PRBool aSetBack); - nsIScrollableView* mScrollableView; nsIBox* mHScrollbarBox; nsIBox* mVScrollbarBox; - nsIFrame* mScrolledFrame; + nsIBox* mScrollAreaBox; nsIBox* mScrollCornerBox; nscoord mOnePixel; nsBoxFrame* mOuter; @@ -156,15 +147,14 @@ public: // value that indicates "not set") PRInt16 mLastDir; - PRPackedBool mNeverHasVerticalScrollbar:1; - PRPackedBool mNeverHasHorizontalScrollbar:1; - PRPackedBool mHasVerticalScrollbar:1; - PRPackedBool mHasHorizontalScrollbar:1; - PRPackedBool mViewInitiatedScroll:1; - PRPackedBool mFrameInitiatedScroll:1; - PRPackedBool mDidHistoryRestore:1; - PRPackedBool mHorizontalOverflow:1; - PRPackedBool mVerticalOverflow:1; + PRPackedBool mNeverHasVerticalScrollbar; + PRPackedBool mNeverHasHorizontalScrollbar; + + PRPackedBool mHasVerticalScrollbar; + PRPackedBool mHasHorizontalScrollbar; + PRPackedBool mViewInitiatedScroll; + PRPackedBool mFrameInitiatedScroll; + PRPackedBool mDidHistoryRestore; }; /** @@ -218,22 +208,12 @@ public: nsIContent ** aNewContent, PRInt32& aContentOffset, PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) { - return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, - aContentOffsetEnd, aBeginFrameContent); - } + PRBool& aBeginFrameContent); virtual nsIFrame* GetContentInsertionFrame() { return mInner.GetScrolledFrame()->GetContentInsertionFrame(); } - virtual nsIView* GetMouseCapturer() const { - return mInner.GetScrolledFrame()->GetView(); - } - - virtual PRBool TypeAlwaysNeedsView() { return PR_TRUE; } - virtual PRBool DoesClipChildren() { return PR_TRUE; } - // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, nsISupportsArray& aAnonymousItems); @@ -366,22 +346,12 @@ public: nsIContent ** aNewContent, PRInt32& aContentOffset, PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) { - return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, - aContentOffsetEnd, aBeginFrameContent); - } + PRBool& aBeginFrameContent); virtual nsIFrame* GetContentInsertionFrame() { return mInner.GetScrolledFrame()->GetContentInsertionFrame(); } - virtual nsIView* GetMouseCapturer() const { - return mInner.GetScrolledFrame()->GetView(); - } - - virtual PRBool TypeAlwaysNeedsView() { return PR_TRUE; } - virtual PRBool DoesClipChildren() { return PR_TRUE; } - // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext, nsISupportsArray& aAnonymousItems); diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 9a588757294..9a0730e4939 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -706,17 +706,12 @@ public: nsFramePaintLayer aWhichLayer, PRUint32 aFlags = 0) = 0; - /** + /* * Does the frame paint its background? If not, then all or part of it will be * painted by ancestors. */ virtual PRBool CanPaintBackground() { return PR_TRUE; } - /** - * Does this frame type always need a view? - */ - virtual PRBool TypeAlwaysNeedsView() { return PR_FALSE; } - /** * Event handling of GUI events. * diff --git a/mozilla/layout/generic/nsObjectFrame.h b/mozilla/layout/generic/nsObjectFrame.h index 646afecb10d..5e94b648da3 100644 --- a/mozilla/layout/generic/nsObjectFrame.h +++ b/mozilla/layout/generic/nsObjectFrame.h @@ -86,7 +86,6 @@ public: virtual nsIAtom* GetType() const; virtual PRBool SupportsVisibilityHidden() { return PR_FALSE; } - virtual PRBool TypeAlwaysNeedsView() { return PR_TRUE; } #ifdef DEBUG NS_IMETHOD GetFrameName(nsAString& aResult) const; diff --git a/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp b/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp index dc2ae724638..22a7e22deee 100644 --- a/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollBoxFrame.cpp @@ -49,6 +49,7 @@ #include "nsCSSRendering.h" #include "nsIScrollableView.h" #include "nsWidgetsCID.h" +#include "nsScrollBoxFrame.h" #include "nsLayoutAtoms.h" #include "nsBoxLayoutState.h" #include "nsIScrollbarMediator.h" @@ -60,6 +61,524 @@ #include "nsITimer.h" #include "nsRepeatService.h" +static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID); + + +//---------------------------------------------------------------------- + +nsresult +NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsScrollBoxFrame* it = new (aPresShell) nsScrollBoxFrame (aPresShell); + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aNewFrame = it; + return NS_OK; +} + +nsScrollBoxFrame::nsScrollBoxFrame(nsIPresShell* aShell):nsBoxFrame(aShell), mVerticalOverflow(PR_FALSE), mHorizontalOverflow(PR_FALSE) +{ +} + +PRBool +nsScrollBoxFrame::NeedsClipWidget() +{ + // Scrollports contained in form controls (e.g., listboxes) don't get + // widgets. + for (nsIFrame* parentFrame = GetParent(); parentFrame; + parentFrame = parentFrame->GetParent()) { + nsIFormControlFrame* fcFrame; + if ((NS_SUCCEEDED(parentFrame->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame)))) { + return PR_FALSE; + } + } + + // Scrollports that don't ever show associated scrollbars don't get + // widgets, because they will seldom actually be scrolled. + nsIFrame* parent = GetParent(); + if (!parent) + return nsnull; + nsCOMPtr scrollFrame = do_QueryInterface(parent); + if (scrollFrame) { + nsGfxScrollFrameInner::ScrollbarStyles scrollbars + = scrollFrame->GetScrollbarStyles(); + if ((scrollbars.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN + || scrollbars.mHorizontal == NS_STYLE_OVERFLOW_VISIBLE) + && (scrollbars.mVertical == NS_STYLE_OVERFLOW_HIDDEN + || scrollbars.mVertical == NS_STYLE_OVERFLOW_VISIBLE)) { + return PR_FALSE; + } + } + + return PR_TRUE; +} + +NS_IMETHODIMP +nsScrollBoxFrame::Init(nsPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsStyleContext* aStyleContext, + nsIFrame* aPrevInFlow) +{ + nsresult rv = nsBoxFrame::Init(aPresContext, aContent, + aParent, aStyleContext, + aPrevInFlow); + + // Create the scrolling view + CreateScrollingView(); + return rv; +} + +NS_IMETHODIMP +nsScrollBoxFrame::SetInitialChildList(nsPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, + aChildList); + + SetUpScrolledFrame(); + + return rv; +} + +void +nsScrollBoxFrame::SetUpScrolledFrame() +{ + NS_ASSERTION(mFrames.GetLength() <= 1, "ScrollBoxes can only have 1 child!"); + + + nsIFrame* frame = mFrames.FirstChild(); + + if (!frame) + return; + + // create a view if we don't already have one. + nsHTMLContainerFrame::CreateViewForFrame(frame, nsnull, PR_TRUE); +} + +NS_IMETHODIMP +nsScrollBoxFrame::AppendFrames(nsIAtom* aListName, + nsIFrame* aFrameList) +{ + nsresult rv = nsBoxFrame::AppendFrames(aListName, aFrameList); + + // make sure we only have 1 child. + NS_ASSERTION(!mFrames.FirstChild()->GetNextSibling(), "Error ScrollBoxes can only have 1 child"); + + SetUpScrolledFrame(); + + return rv; +} + +NS_IMETHODIMP +nsScrollBoxFrame::InsertFrames(nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList) +{ + nsresult rv = nsBoxFrame::InsertFrames(aListName, aPrevFrame, aFrameList); + + // make sure we only have 1 child. + NS_ASSERTION(!mFrames.FirstChild()->GetNextSibling(), "Error ScrollBoxes can only have 1 child"); + + SetUpScrolledFrame(); + + return rv; +} + +NS_IMETHODIMP +nsScrollBoxFrame::RemoveFrame(nsIAtom* aListName, + nsIFrame* aOldFrame) +{ + nsresult rv = nsBoxFrame::RemoveFrame(aListName, aOldFrame); + + SetUpScrolledFrame(); + + return rv; +} + +nsresult +nsScrollBoxFrame::CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay) +{ + nsresult rv = NS_OK; + // If it's fixed positioned, then create a widget + if (NS_STYLE_POSITION_FIXED == aDisplay->mPosition) { + rv = aView->CreateWidget(kWidgetCID); + } + + return(rv); +} + +nsresult +nsScrollBoxFrame::GetScrollingParentView(nsIFrame* aParent, + nsIView** aParentView) +{ + *aParentView = aParent->GetView(); + NS_ASSERTION(*aParentView, "GetParentWithView failed"); + return NS_OK; +} + +nsIView* +nsScrollBoxFrame::GetMouseCapturer() const +{ + nsIScrollableView* scrollingView = GetView()->ToScrollableView(); + NS_ASSERTION(scrollingView, + "Scrollbox does not contain a scrolling view?"); + nsIView* view; + scrollingView->GetScrolledView(view); + NS_ASSERTION(view, "Scrolling view does not have a scrolled view"); + return view; +} + +nsresult +nsScrollBoxFrame::CreateScrollingView() +{ + //Get parent frame + nsIFrame* parent = GetAncestorWithView(); + NS_ASSERTION(parent, "GetParentWithView failed"); + + // Get parent view + nsIView* parentView = nsnull; + GetScrollingParentView(parent, &parentView); + + // Get the view manager + nsIViewManager* viewManager = parentView->GetViewManager(); + + // Create the scrolling view + nsIScrollableView* scrollingView = viewManager->CreateScrollableView(mRect, parentView); + + if (scrollingView) { + // Initialize the scrolling view + nsIView* view = scrollingView->View(); + + SyncFrameViewProperties(GetPresContext(), this, mStyleContext, view); + + // Insert the view into the view hierarchy + // XXX Put view last in document order until we know how to do better + viewManager->InsertChild(parentView, view, nsnull, PR_TRUE); + + // If it's fixed positioned, then create a widget too + CreateScrollingViewWidget(view, GetStyleDisplay()); + + // Have the scrolling view create its internal widgets + if (NeedsClipWidget()) { + scrollingView->CreateScrollControls(); + } + + // Remember our view + SetView(view); + + return NS_OK; + } + return NS_ERROR_OUT_OF_MEMORY; +} + +NS_IMETHODIMP +nsScrollBoxFrame::GetMargin(nsMargin& aMargin) +{ + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollBoxFrame::GetPadding(nsMargin& aMargin) +{ + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollBoxFrame::GetBorder(nsMargin& aMargin) +{ + aMargin.SizeTo(0,0,0,0); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollBoxFrame::DoLayout(nsBoxLayoutState& aState) +{ + PRUint32 oldflags = aState.LayoutFlags(); + + nsRect clientRect(0,0,0,0); + GetClientRect(clientRect); + nsIBox* kid = nsnull; + GetChildBox(&kid); + nsRect childRect(clientRect); + nsMargin margin(0,0,0,0); + kid->GetMargin(margin); + childRect.Deflate(margin); + + nsPresContext* presContext = aState.PresContext(); + + PRBool isBoxWrapped = kid->IsBoxWrapped(); + + // see if our child is html. If it is then + // never include the overflow. The child will be the size + // given but its view will include the overflow size. + if (isBoxWrapped) + kid->SetIncludeOverflow(PR_FALSE); + + PRInt32 flags = NS_FRAME_NO_MOVE_VIEW; + + // if the child is not a box, then we can't use + // min size. the child technically can get as small as it wants + // to. + if (!isBoxWrapped) { + nsSize min(0,0); + kid->GetMinSize(aState, min); + + if (min.height > childRect.height) + childRect.height = min.height; + + if (min.width > childRect.width) + childRect.width = min.width; + } else { + // don't size the view if our child isn't a box + flags |= NS_FRAME_NO_SIZE_VIEW; + } + + aState.SetLayoutFlags(flags); + kid->SetBounds(aState, childRect); + kid->Layout(aState); + + childRect = kid->GetRect(); + + clientRect.Inflate(margin); + + // now size the view to the size including our overflow. + if (isBoxWrapped) { + nsSize overflow(0,0); + kid->GetOverflow(overflow); + childRect.width = overflow.width; + childRect.height = overflow.height; + } + + if (childRect.width < clientRect.width || childRect.height < clientRect.height) + { + if (childRect.width < clientRect.width) + childRect.width = clientRect.width; + + if (childRect.height < clientRect.height) + childRect.height = clientRect.height; + + clientRect.Deflate(margin); + + // remove overflow area when we update the bounds, + // because we've already accounted for it + kid->SetBounds(aState, childRect, PR_TRUE); + } + + aState.SetLayoutFlags(oldflags); + + SyncLayout(aState); + + if (isBoxWrapped) { + nsRect r(0, 0, childRect.width, childRect.height); + nsContainerFrame::SyncFrameViewAfterReflow(presContext, kid, + kid->GetView(), &r, NS_FRAME_NO_MOVE_VIEW); + } + + nsIView* view = GetView(); + nsIScrollableView* scrollingView = view->ToScrollableView(); + if (scrollingView) { + scrollingView->ComputeScrollOffsets(PR_TRUE); + } + + childRect = kid->GetRect(); + + // first see what changed + PRBool vertChanged = PR_FALSE; + PRBool horizChanged = PR_FALSE; + + if (mVerticalOverflow && childRect.height <= mRect.height) { + mVerticalOverflow = PR_FALSE; + vertChanged = PR_TRUE; + } else if (childRect.height > mRect.height) { + if (!mVerticalOverflow) { + mVerticalOverflow = PR_TRUE; + } + vertChanged = PR_TRUE; + } + + if (mHorizontalOverflow && childRect.width <= mRect.width) { + mHorizontalOverflow = PR_FALSE; + horizChanged = PR_TRUE; + } else if (childRect.width > mRect.width) { + if (!mHorizontalOverflow) { + mHorizontalOverflow = PR_TRUE; + } + horizChanged = PR_TRUE; + } + + // if either changed + if (vertChanged || horizChanged) + { + // are there 2 events or 1? + if (vertChanged && horizChanged) { + if (mVerticalOverflow == mHorizontalOverflow) + { + // both either overflowed or underflowed. 1 event + PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::both); + } else { + // one overflowed and one underflowed + PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::vertical); + PostScrollPortEvent(mHorizontalOverflow, nsScrollPortEvent::horizontal); + } + } else if (vertChanged) // only one changed either vert or horiz + PostScrollPortEvent(mVerticalOverflow, nsScrollPortEvent::vertical); + else + PostScrollPortEvent(mHorizontalOverflow, nsScrollPortEvent::horizontal); + } + + return NS_OK; +} + +void +nsScrollBoxFrame::PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType) +{ + if (!mContent) + return; + + nsScrollPortEvent* event = new nsScrollPortEvent(aOverflow ? + NS_SCROLLPORT_OVERFLOW : + NS_SCROLLPORT_UNDERFLOW); + event->orient = aType; + GetPresContext()->PresShell()->PostDOMEvent(mContent, event); +} + + +NS_IMETHODIMP +nsScrollBoxFrame::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 +nsScrollBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + nsresult rv = child->GetPrefSize(aBoxLayoutState, aSize); + AddMargin(child, aSize); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSPrefSize(aBoxLayoutState, this, aSize); + return rv; +} + +NS_IMETHODIMP +nsScrollBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + aSize = child->GetMinSizeForScrollArea(aBoxLayoutState); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMinSize(aBoxLayoutState, this, aSize); + return NS_OK; +} + +NS_IMETHODIMP +nsScrollBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize) +{ + nsIBox* child = nsnull; + GetChildBox(&child); + nsresult rv = child->GetMaxSize(aBoxLayoutState, aSize); + AddMargin(child, aSize); + AddBorderAndPadding(aSize); + AddInset(aSize); + nsIBox::AddCSSMaxSize(aBoxLayoutState, this, aSize); + return rv; +} + +NS_IMETHODIMP +nsScrollBoxFrame::Paint(nsPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer, + PRUint32 aFlags) +{ + if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + // Only paint the border and background if we're visible + + if (GetStyleVisibility()->IsVisibleOrCollapsed()) { + // Paint our border only (no background) + const nsStyleBorder* border = GetStyleBorder(); + + nsRect rect(0, 0, mRect.width, mRect.height); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, + aDirtyRect, rect, *border, mStyleContext, 0); + } + } + + // Paint our children + nsBoxFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + + // Call nsFrame::Paint to draw selection border when appropriate + return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + +nsresult +nsScrollBoxFrame::GetContentOf(nsIContent** aContent) +{ + *aContent = GetContent(); + NS_IF_ADDREF(*aContent); + return NS_OK; +} + +nsIAtom* +nsScrollBoxFrame::GetType() const +{ + return nsLayoutAtoms::scrollFrame; +} + +#ifdef NS_DEBUG +NS_IMETHODIMP +nsScrollBoxFrame::GetFrameName(nsAString& aResult) const +{ + return MakeFrameName(NS_LITERAL_STRING("ScrollBox"), aResult); +} +#endif + +NS_IMETHODIMP_(nsrefcnt) +nsScrollBoxFrame::AddRef(void) +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) +nsScrollBoxFrame::Release(void) +{ + return NS_OK; +} + + +NS_INTERFACE_MAP_BEGIN(nsScrollBoxFrame) + NS_INTERFACE_MAP_ENTRY(nsIBox) +#ifdef NS_DEBUG + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) +#endif + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) +NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) + + class nsAutoRepeatBoxFrame : public nsButtonBoxFrame, public nsITimerCallback { diff --git a/mozilla/layout/xul/base/src/nsScrollBoxFrame.h b/mozilla/layout/xul/base/src/nsScrollBoxFrame.h index 12de158abc1..a4de54bd130 100644 --- a/mozilla/layout/xul/base/src/nsScrollBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsScrollBoxFrame.h @@ -41,4 +41,102 @@ #include "nsIStatefulFrame.h" #include "nsGUIEvent.h" +/** + * The scroll frame creates and manages the scrolling view + * + * It only supports having a single child frame that typically is an area + * frame, but doesn't have to be. The child frame must have a view, though + * + * Scroll frames don't support incremental changes, i.e. you can't replace + * or remove the scrolled frame + */ +class nsScrollBoxFrame : public nsBoxFrame { +public: + friend nsresult NS_NewScrollBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + + NS_IMETHOD Init(nsPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsStyleContext* aContext, + nsIFrame* aPrevInFlow); + + // Called to set the one and only child frame. Returns NS_ERROR_INVALID_ARG + // if the child frame is NULL, and NS_ERROR_UNEXPECTED if the child list + // contains more than one frame + NS_IMETHOD SetInitialChildList(nsPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + + // Because there can be only one child frame, these two function return + // NS_ERROR_FAILURE + NS_IMETHOD AppendFrames(nsIAtom* aListName, + nsIFrame* aFrameList); + NS_IMETHOD InsertFrames(nsIAtom* aListName, + nsIFrame* aPrevFrame, + nsIFrame* aFrameList); + + // This function returns NS_ERROR_NOT_IMPLEMENTED + NS_IMETHOD RemoveFrame(nsIAtom* aListName, + nsIFrame* aOldFrame); + + + NS_IMETHOD Paint(nsPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer, + PRUint32 aFlags = 0); + + /** + * Get the "type" of the frame + * + * @see nsLayoutAtoms::scrollFrame + */ + virtual nsIAtom* GetType() const; + + /** + * This frame does clip its child (the scrolled frame). + */ + virtual PRBool DoesClipChildren() { return PR_TRUE; } + +#ifdef NS_DEBUG + NS_IMETHOD GetFrameName(nsAString& aResult) const; +#endif + + // nsIBox methods + NS_DECL_ISUPPORTS + + 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 DoLayout(nsBoxLayoutState& aBoxLayoutState); + NS_IMETHOD GetPadding(nsMargin& aMargin); + NS_IMETHOD GetBorder(nsMargin& aMargin); + NS_IMETHOD GetMargin(nsMargin& aMargin); + + virtual nsresult GetContentOf(nsIContent** aContent); + + virtual nsIView* GetMouseCapturer() const; + +protected: + nsScrollBoxFrame(nsIPresShell* aShell); + + // Creation of the widget for the scrolling view is factored into a virtual method so + // that sub-classes may control widget creation. + virtual nsresult CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay); + // Getting the view for scollframe may be overriden to provide a parent view for te scroll frame + virtual nsresult GetScrollingParentView(nsIFrame* aParent, + nsIView** aParentView); + +private: + nsresult CreateScrollingView(); + PRPackedBool mVerticalOverflow; + PRPackedBool mHorizontalOverflow; + +protected: + virtual PRBool NeedsClipWidget(); + virtual void PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType); + virtual void SetUpScrolledFrame(); +}; + #endif /* nsScrollBoxFrame_h___ */