diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index 5929c85fabf..6852aaed671 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -1707,7 +1707,7 @@ NS_IMETHODIMP StyleSetImpl::ContentInserted(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aIndexInContainer) { - return mFrameConstructor->ContentInserted(aPresContext, aContainer, + return mFrameConstructor->ContentInserted(aPresContext, aContainer, nsnull, aChild, aIndexInContainer, nsnull, PR_FALSE); } diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 035fa753f58..e9f5bf51ce4 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -1594,7 +1594,7 @@ nsEventStateManager::DoWheelScroll(nsIPresContext* aPresContext, nsCOMPtr svp = do_QueryInterface(focusFrame); if (svp) { - svp->GetScrollableView(&sv); + svp->GetScrollableView(aPresContext, &sv); if (sv) CallQueryInterface(sv, &focusView); } else { diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 5f79293a80b..16030e35552 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -187,6 +187,7 @@ NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aN #include "nsIScrollable.h" #include "nsINodeInfo.h" #include "prenv.h" +#include "nsWidgetsCID.h" // Global object maintenance nsIXBLService * nsCSSFrameConstructor::gXBLService = nsnull; @@ -2573,7 +2574,7 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewInnerFrame, - childItems); + PR_FALSE, childItems); // Set the inner table frame's initial primary list aNewInnerFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -2695,7 +2696,7 @@ nsCSSFrameConstructor::ConstructTableRowGroupFrame(nsIPresShell* aPre if (NS_FAILED(rv)) return rv; // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (aIsPseudoParent) { @@ -2806,7 +2807,7 @@ nsCSSFrameConstructor::ConstructTableRowFrame(nsIPresShell* aPresShel if (NS_FAILED(rv)) return rv; // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (aIsPseudoParent) { @@ -3546,7 +3547,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, // This must happen before ProcessChildren to ensure that popups are // never constructed before the popupset. CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aDocElement, contentFrame, - childItems, PR_TRUE); + PR_FALSE, childItems, PR_TRUE); ProcessChildren(aPresShell, aPresContext, aState, aDocElement, contentFrame, PR_TRUE, childItems, isBlockFrame); @@ -3874,6 +3875,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIFrame* newScrollableFrame = nsnull; + newFrame = nsnull; rootPseudoStyle = BeginBuildingScrollFrame( aPresShell, aPresContext, state, @@ -4357,6 +4359,11 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, nsIFrame* scrolledFrame = nsnull; NS_NewSelectsAreaFrame(aPresShell, &scrolledFrame, flags); + // make sure any existing anonymous content is cleared out. Gfx scroll frame construction + // should reset it to just be the anonymous scrollbars, but we don't want to depend + // on that. + aPresShell->SetAnonymousContentFor(aContent, nsnull); + InitializeSelectFrame(aPresShell, aPresContext, aState, listFrame, scrolledFrame, aContent, comboboxFrame, listStyle, PR_FALSE, PR_FALSE, PR_TRUE); newFrame = listFrame; @@ -4381,10 +4388,12 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, NS_RELEASE(viewWidget); //listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - // Create display and button frames from the combobox's anonymous content + // Create display and button frames from the combobox's anonymous content. + // The anonymous content is appended to existing anonymous content for this + // element (the scrollbars). nsFrameItems childItems; CreateAnonymousFrames(aPresShell, aPresContext, nsHTMLAtoms::combobox, - aState, aContent, comboboxFrame, childItems); + aState, aContent, comboboxFrame, PR_TRUE, childItems); comboboxFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -4429,14 +4438,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, aNewFrame = listFrame; - // Set flag so the events go to the listFrame not child frames. - // XXX: We should replace this with a real widget manager similar - // to how the nsFormControlFrame works. - // Re-directing events is a temporary Kludge. - nsIView *listView; - listFrame->GetView(aPresContext, &listView); - NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); - //listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } } @@ -4460,7 +4461,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, nsStyleContext* aStyleContext, PRBool aIsAbsolutelyPositioned, PRBool aIsFixedPositioned, - PRBool aCreateBlock) + PRBool aBuildCombobox) { // Initialize it nsIFrame* geometricParent = aParentFrame; @@ -4471,24 +4472,48 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, geometricParent = aState.mFixedItems.containingBlock; } - nsRefPtr scrolledPseudoStyle; + // We don't call InitAndRestoreFrame for scrollFrame because we can only + // restore the frame state after its parts have been created (in particular, + // the scrollable view). So we have to split Init and Restore. - - scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsCSSAnonBoxes::scrolledContent, - aStyleContext); + // Initialize the frame + scrollFrame->Init(aPresContext, aContent, geometricParent, aStyleContext, nsnull); - InitAndRestoreFrame(aPresContext, aState, aContent, - geometricParent, aStyleContext, nsnull, scrollFrame); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, scrollFrame, + aStyleContext, aParentFrame, aBuildCombobox); + if (aBuildCombobox) { + // Give the drop-down list a popup widget + nsIView * view; + scrollFrame->GetView(aPresContext, &view); + NS_ASSERTION(view, "We asked for a view but didn't get one"); + if (view) { + nsCOMPtr vm; + view->GetViewManager(*getter_AddRefs(vm)); + vm->SetViewFloating(view, PR_TRUE); - // Initialize the frame and force it to have a view - // the scrolled frame is anonymous and does not have a content node - InitAndRestoreFrame(aPresContext, aState, aContent, - scrollFrame, scrolledPseudoStyle, nsnull, scrolledFrame); + nsWidgetInitData widgetData; + widgetData.mWindowType = eWindowType_popup; + widgetData.mBorderStyle = eBorderStyle_default; - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, scrolledFrame, - scrolledPseudoStyle, nsnull, PR_TRUE); +#if defined(XP_MAC) || defined(XP_MACOSX) + static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); + view->CreateWidget(kCPopUpCID, &widgetData, nsnull); +#else + static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); + view->CreateWidget(kCChildCID, &widgetData, nsnull); +#endif + } + } + nsStyleContext* scrolledPseudoStyle; + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, + scrolledFrame, geometricParent, aParentFrame, scrollFrame, + scrolledPseudoStyle); + + if (aState.mFrameState && aState.mFrameManager) { + // Restore frame state for the scroll frame + aState.mFrameManager->RestoreFrameStateFor(aPresContext, scrollFrame, aState.mFrameState); + } // The area frame is a floater container PRBool haveFirstLetterStyle, haveFirstLineStyle; @@ -4541,17 +4566,9 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, aState.mFloatedItems.childList); } - // Set the scroll frame's initial child list - scrollFrame->SetInitialChildList(aPresContext, nsnull, scrolledFrame); - return NS_OK; } -/** - * Used to be InitializeScrollFrame but now its only used for the select tag - * But the select tag should really be fixed to use GFX scrollbars that can - * be create with BuildScrollFrame. - */ nsresult nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIPresContext* aPresContext, @@ -5071,7 +5088,7 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell, // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list @@ -5229,6 +5246,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell nsFrameConstructorState& aState, nsIContent* aParent, nsIFrame* aNewFrame, + PRBool aAppendToExisting, nsFrameItems& aChildItems, PRBool aIsRoot) { @@ -5252,7 +5270,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell ) return NS_OK; - return CreateAnonymousFrames(aPresShell, aPresContext, aState, aParent, mDocument, aNewFrame, aChildItems); + return CreateAnonymousFrames(aPresShell, aPresContext, aState, aParent, + mDocument, aNewFrame, aAppendToExisting, aChildItems); } // after the node has been constructed and initialized create any @@ -5264,6 +5283,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell nsIContent* aParent, nsIDocument* aDocument, nsIFrame* aParentFrame, + PRBool aAppendToExisting, nsFrameItems& aChildItems) { nsCOMPtr creator(do_QueryInterface(aParentFrame)); @@ -5279,6 +5299,29 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell anonymousItems->Count(&count); if (count) { + // A content element can have multiple sources of anonymous content. For example, + // SELECTs have a combobox dropdown button and also scrollbars in the list view. + // nsPresShell doesn't handle this very well. It's a problem because a reframe could + // cause anonymous content from one source to be destroyed and recreated while + // (in theory) leaving the rest intact, but the presshell doesn't have a way of tracking + // the anonymous content at that granularity. + + // So what we're doing right now is wiping out existing content whenever we get new + // anonymous content, except for the one case we care about where there are multiple + // sources (SELECTs). This case is handled by having SELECT initialization tell us + // explicitly not to wipe out the scrollbars when the combobox anonymous content is + // added. + // Note that we only wipe out existing content when there is actual new content. + // Otherwise we wipe out scrollbars and other anonymous content when we check sources + // that never provide anonymous content (e.g. the call to CreateAnonymousFrames + // from ConstructBlock). + + // What we SHOULD do is get rid of the presshell's need to track anonymous + // content. It's only used for cleanup as far as I can tell. + if (!aAppendToExisting) { + aPresShell->SetAnonymousContentFor(aParent, nsnull); + } + // Inform the pres shell about the anonymous content aPresShell->SetAnonymousContentFor(aParent, anonymousItems); @@ -5912,7 +5955,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, } CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, - newFrame, childItems); + newFrame, PR_FALSE, childItems); // Set the frame's initial child list newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6028,7 +6071,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresSh nsIFrame* scrollFrame = nsnull; nsIFrame* parentFrame = nsnull; - nsIFrame* gfxScrollFrame = nsnull; + nsIFrame* gfxScrollFrame = aNewFrame; nsFrameItems anonymousItems; @@ -6037,9 +6080,20 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresSh PRBool isGfx = HasGfxScrollbars(); if (isGfx) { - BuildGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, - aParentFrame, aContentParentFrame, contentStyle, - aIsRoot, gfxScrollFrame, anonymousItems, aScrollPortFrame); + if (!gfxScrollFrame) { + NS_NewGfxScrollFrame(aPresShell, &gfxScrollFrame, aDocument, aIsRoot); + + InitAndRestoreFrame(aPresContext, aState, aContent, + aParentFrame, contentStyle, nsnull, gfxScrollFrame); + + // Create a view + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, gfxScrollFrame, + contentStyle, aContentParentFrame, PR_FALSE); + } + + InitGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, + aParentFrame, aContentParentFrame, contentStyle, + aIsRoot, gfxScrollFrame, anonymousItems, aScrollPortFrame); scrollFrame = anonymousItems.childList; // get the scrollport from the anonymous list parentFrame = gfxScrollFrame; @@ -6182,6 +6236,7 @@ nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIPresContext* aPresConte * * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the * scrolled frame you passed in. (returned) + * If this is not null, we'll just use it * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned) */ nsresult @@ -6256,32 +6311,24 @@ nsCSSFrameConstructor::BuildScrollFrame(nsIPresShell* aPresShell, /** * 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::BuildGfxScrollFrame (nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aContent, - nsIDocument* aDocument, - nsIFrame* aParentFrame, - nsIFrame* aContentParentFrame, - nsStyleContext* aStyleContext, - PRBool aIsRoot, - nsIFrame*& aNewFrame, - nsFrameItems& aAnonymousFrames, - nsIFrame* aScrollPortFrame) +nsCSSFrameConstructor::InitGfxScrollFrame(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames, + nsIFrame* aScrollPortFrame) { #ifdef INCLUDE_XUL - NS_NewGfxScrollFrame(aPresShell, &aNewFrame, aDocument, aIsRoot); - - InitAndRestoreFrame(aPresContext, aState, aContent, - aParentFrame, aStyleContext, nsnull, aNewFrame); - - // Create a view - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, - aStyleContext, aContentParentFrame, PR_FALSE); - - if (!aScrollPortFrame) NS_NewScrollPortFrame(aPresShell, &aScrollPortFrame); @@ -6289,7 +6336,7 @@ nsCSSFrameConstructor::BuildGfxScrollFrame (nsIPresShell* aPresShell, // if there are any anonymous children for the nsScrollFrame create frames for them. CreateAnonymousFrames(aPresShell, aPresContext, aState, aContent, aDocument, aNewFrame, - aAnonymousFrames); + PR_FALSE, aAnonymousFrames); return NS_OK; #endif @@ -6420,7 +6467,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the scrolled frame's initial child lists scrolledFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6485,7 +6532,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list(s) newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6537,7 +6584,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list(s) newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -7063,7 +7110,7 @@ nsCSSFrameConstructor::ConstructMathMLFrame(nsIPresShell* aPresShell, childItems, PR_FALSE); CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); } // Set the frame's initial child list @@ -7207,7 +7254,7 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsIPresShell* aPresShell, newFrame, PR_TRUE, childItems, isBlock); CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); } // Set the frame's initial child list @@ -8429,7 +8476,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, nsIContent* item = nsCOMPtr(*iter); if (item == child) // Call ContentInserted with this index. - ContentInserted(aPresContext, aContainer, child, iter.index(), mTempFrameTreeState, PR_FALSE); + ContentInserted(aPresContext, aContainer, nsnull, child, iter.index(), mTempFrameTreeState, PR_FALSE); } } @@ -8932,6 +8979,7 @@ nsCSSFrameConstructor::NeedSpecialFrameReframe(nsIPresShell* aPresShell, NS_IMETHODIMP nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nsIContent* aContainer, + nsIFrame* aContainerFrame, nsIContent* aChild, PRInt32 aIndexInContainer, nsILayoutHistoryState* aFrameState, @@ -8939,7 +8987,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, { // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and // the :empty pseudo-class? - #ifdef DEBUG if (gNoisyContentUpdates) { printf("nsCSSFrameConstructor::ContentInserted container=%p child=%p index=%d\n", @@ -9060,10 +9107,13 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } // Otherwise, we've got parent content. Find its frame. - nsIFrame* parentFrame = GetFrameFor(shell, aPresContext, aContainer); - if (! parentFrame) - return NS_OK; // XXXwaterson will this break selects? (See ``Here - // we have been notified...'' below.) + nsIFrame* parentFrame = aContainerFrame; + if (!parentFrame) { + parentFrame = GetFrameFor(shell, aPresContext, aContainer); + if (! parentFrame) + return NS_OK; // XXXwaterson will this break selects? (See ``Here + // we have been notified...'' below.) + } // See if we have an XBL insertion point. If so, then that's our // real parent frame; if not, then the frame hasn't been built yet @@ -9385,7 +9435,7 @@ nsCSSFrameConstructor::ContentReplaced(nsIPresContext* aPresContext, aOldChild, aIndexInContainer, PR_TRUE); if (NS_SUCCEEDED(res)) { - res = ContentInserted(aPresContext, aContainer, + res = ContentInserted(aPresContext, aContainer, nsnull, aNewChild, aIndexInContainer, nsnull, PR_TRUE); } @@ -9678,10 +9728,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, // For "select" add the pseudo frame after the last item is deleted nsIFrame* parentFrame = nsnull; childFrame->GetParent(&parentFrame); - if (parentFrame == selectFrame) { - return NS_ERROR_FAILURE; - } - if (shell && parentFrame) { + if (shell && parentFrame && parentFrame != selectFrame) { nsFrameConstructorState state(aPresContext, nsnull, nsnull, nsnull); AddDummyFrameToSelect(aPresContext, shell, state, @@ -12108,20 +12155,25 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, nsCOMPtr container; aContent->GetParent(*getter_AddRefs(container)); if (container) { - PRInt32 indexInContainer; + PRInt32 indexInContainer; rv = container->IndexOf(aContent, indexInContainer); if (NS_SUCCEEDED(rv)) { // Before removing the frames associated with the content object, ask them to save their // state onto a temporary state object. CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); + // Save parent frame because this frame is going away + nsIFrame* parent = nsnull; + if (frame) + frame->GetParent(&parent); + // Remove the frames associated with the content object on which the // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); if (NS_SUCCEEDED(rv)) { // Now, recreate the frames associated with this content object. - rv = ContentInserted(aPresContext, container, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); + rv = ContentInserted(aPresContext, container, parent, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); } } } else { @@ -13374,7 +13426,7 @@ nsCSSFrameConstructor::ConstructBlock(nsIPresShell* aPresShell, nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -13515,7 +13567,7 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell, nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index 47780b79b0c..11474eca27e 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -107,6 +107,7 @@ public: NS_IMETHOD ContentInserted(nsIPresContext* aPresContext, nsIContent* aContainer, + nsIFrame* aContainerFrame, nsIContent* aChild, PRInt32 aIndexInContainer, nsILayoutHistoryState* aFrameState, @@ -574,22 +575,24 @@ protected: nsFrameItems& aFrameItems, PRBool aXBLBaseTag); - nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsIAtom* aTag, - nsFrameConstructorState& aState, - nsIContent* aParent, - nsIFrame* aNewFrame, - nsFrameItems& aChildItems, - PRBool aIsRoot = PR_FALSE); + nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsIAtom* aTag, + nsFrameConstructorState& aState, + nsIContent* aParent, + nsIFrame* aNewFrame, + PRBool aAppendToExisting, + nsFrameItems& aChildItems, + PRBool aIsRoot = PR_FALSE); - nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aParent, - nsIDocument* aDocument, - nsIFrame* aNewFrame, - nsFrameItems& aChildItems); + nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aParent, + nsIDocument* aDocument, + nsIFrame* aNewFrame, + PRBool aAppendToExisting, + nsFrameItems& aChildItems); //MathML Mod - RBS #ifdef MOZ_MATHML @@ -737,18 +740,18 @@ protected: // Creates a new GfxScrollFrame, Initializes it, and creates a scroll port for it // nsresult - BuildGfxScrollFrame(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aContent, - nsIDocument* aDocument, - nsIFrame* aParentFrame, - nsIFrame* aContentParentFrame, - nsStyleContext* aStyleContext, - PRBool aIsRoot, - nsIFrame*& aNewFrame, - nsFrameItems& aAnonymousFrames, - nsIFrame* aScrollPort = nsnull); + InitGfxScrollFrame(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames, + nsIFrame* aScrollPort = nsnull); nsresult diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index b1b1d78c428..96fcfae8719 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -2389,9 +2389,17 @@ FrameManager::GenerateStateKey(nsIContent* aContent, // Hash by index of control in doc (we are not in a form) // These are important as they are unique, and type/name may not be. + + // We don't refresh the form control list here (passing PR_TRUE + // for aFlush), although we really should. Forcing a flush + // causes a signficant pageload performance hit. See bug + // 166636. Doing this wrong means you will see the assertion + // below being hit. mHTMLFormControls->IndexOf(aContent, index, PR_FALSE); NS_ASSERTION(index > -1, - "nsFrameManager::GenerateStateKey didn't find content by type!"); + "nsFrameManager::GenerateStateKey didn't find content " + "by type! See bug 139568"); + if (index > -1) { KeyAppendInt(index, aKey); generatedUniqueKey = PR_TRUE; diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 756bb16efec..a94da9fa614 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -504,7 +504,9 @@ public: /** * Store the nsIAnonymousContentCreator-generated anonymous - * content that's associated with an element. + * content that's associated with an element. The new anonymous content + * is added to whatever anonymous content might already be associated with + * the element. * @param aContent the element with which the anonymous * content is to be associated with * @param aAnonymousElements an array of nsIContent diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 756bb16efec..a94da9fa614 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -504,7 +504,9 @@ public: /** * Store the nsIAnonymousContentCreator-generated anonymous - * content that's associated with an element. + * content that's associated with an element. The new anonymous content + * is added to whatever anonymous content might already be associated with + * the element. * @param aContent the element with which the anonymous * content is to be associated with * @param aAnonymousElements an array of nsIContent diff --git a/mozilla/layout/base/public/nsIScrollableFrame.h b/mozilla/layout/base/public/nsIScrollableFrame.h index 8682d7cdf45..67e90c6275b 100644 --- a/mozilla/layout/base/public/nsIScrollableFrame.h +++ b/mozilla/layout/base/public/nsIScrollableFrame.h @@ -41,6 +41,7 @@ #include "nsISupports.h" #include "nsCoord.h" #include "nsIViewManager.h" +#include "nsIScrollableViewProvider.h" class nsIFrame; class nsIBox; @@ -51,7 +52,7 @@ class nsIPresContext; { 0xc95f1831, 0xc372, 0x11d1, \ { 0xb7, 0x21, 0x0, 0x64, 0x9, 0x92, 0xd8, 0xc9 } } -class nsIScrollableFrame : public nsISupports { +class nsIScrollableFrame : public nsIScrollableViewProvider { public: enum nsScrollPref { diff --git a/mozilla/layout/base/public/nsIScrollableViewProvider.h b/mozilla/layout/base/public/nsIScrollableViewProvider.h index 622a7cacbf6..e2ea88323f6 100644 --- a/mozilla/layout/base/public/nsIScrollableViewProvider.h +++ b/mozilla/layout/base/public/nsIScrollableViewProvider.h @@ -37,7 +37,7 @@ class nsIScrollableViewProvider : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEWPROVIDER_IID) - NS_IMETHOD GetScrollableView(nsIScrollableView** aView)=0; + NS_IMETHOD GetScrollableView(nsIPresContext* aContext, nsIScrollableView** aResult)=0; }; #endif /* _nsIScrollableViewProvider_h */ diff --git a/mozilla/layout/base/public/nsIStyleFrameConstruction.h b/mozilla/layout/base/public/nsIStyleFrameConstruction.h index acc8c6f80e8..2bc330c6b8b 100644 --- a/mozilla/layout/base/public/nsIStyleFrameConstruction.h +++ b/mozilla/layout/base/public/nsIStyleFrameConstruction.h @@ -115,6 +115,9 @@ public: * * @param aPresContext the presentation context * @param aContainer the content node into which content was appended + * @param aContainerFrame the frame which the content will be inserted under if + * aContainer has more than one frame; may be null, in which + * case primary frame is used. * @param aChild the content node that was inserted * @param aNewIndexInContainer the index of aChild in aContainer * @param aFrameState the layout history object used to initialize the new frame(s) @@ -127,6 +130,7 @@ public: */ NS_IMETHOD ContentInserted(nsIPresContext* aPresContext, nsIContent* aContainer, + nsIFrame* aContainerFrame, nsIContent* aChild, PRInt32 aIndexInContainer, nsILayoutHistoryState* aFrameState, diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index ea676373a57..40fb579e769 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -756,7 +756,7 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, // move the dropdown list up dropdownYOffset = - (dropdownRect.height); } - } + } dropdownRect.x = 0; dropdownRect.y = dropdownYOffset; @@ -764,10 +764,6 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, mDropdownFrame->GetRect(currentRect); mDropdownFrame->SetRect(aPresContext, dropdownRect); -#ifdef DEBUG_rodsXXXXXX - printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); -#endif - return rv; } @@ -1594,8 +1590,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, REFLOW_DEBUG_MSG("Unconstrained.....\n"); REFLOW_DEBUG_MSG4("*B mItemDisplayWidth %d dropdownRect.width:%d dropdownRect.w+h %d\n", PX(mItemDisplayWidth), PX(dropdownRect.width), PX((dropBorderPadding.left + dropBorderPadding.right))); - // Start with the dropdown rect's width - mItemDisplayWidth = dropdownRect.width; + // Start with the dropdown rect's width (at this stage, it's the + // natural width of the content in the list, i.e., the width of + // the widest content, i.e. the preferred width for the display + // frame) and add room for the button, which is assumed to match + // the width of the scrollbar (note that the scrollbarWidth is + // passed as aBtnWidth to ReflowCombobox). (When the dropdown was + // an nsScrollFrame the scrollbar width seems to have already been + // added to its unconstrained width.) + mItemDisplayWidth = dropdownRect.width + scrollbarWidth; REFLOW_DEBUG_MSG2("* mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); @@ -2584,18 +2587,20 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, //nsIScrollableViewProvider //---------------------------------------------------------------------- NS_METHOD -nsComboboxControlFrame::GetScrollableView(nsIScrollableView** aView) +nsComboboxControlFrame::GetScrollableView(nsIPresContext* aPresContext, + nsIScrollableView** aView) { *aView = nsnull; - nsIView* view = nsnull; - mDropdownFrame->GetView(mPresContext, &view); - if (view) { - nsIScrollableView* sv = nsnull; - nsresult rv = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**) &sv); - if (NS_SUCCEEDED(rv) && sv) - *aView = sv; - } - return NS_OK; + + if (!mDropdownFrame) + return NS_ERROR_FAILURE; + + nsIScrollableFrame* scrollable = nsnull; + nsresult rv = CallQueryInterface(mDropdownFrame, &scrollable); + if (NS_FAILED(rv)) + return rv; + + return scrollable->GetScrollableView(aPresContext, aView); } //--------------------------------------------------------- diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 6057ab3eb6f..144378364cd 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -212,7 +212,7 @@ public: { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! // nsIScrollableViewProvider - NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + NS_IMETHOD GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView); //nsIStatefulFrame NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index be91a5f54aa..75bce68414b 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -46,6 +46,8 @@ #include "nsIHTMLContent.h" #include "nsIFormControl.h" #include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLOptionsCollection.h" #include "nsIDOMNSHTMLOptionCollectn.h" #include "nsIDOMHTMLSelectElement.h" @@ -117,7 +119,9 @@ NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsListControlFrame* it = new (aPresShell) nsListControlFrame; + nsCOMPtr doc; + aPresShell->GetDocument(getter_AddRefs(doc)); + nsListControlFrame* it = new (aPresShell) nsListControlFrame(aPresShell, doc); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -397,8 +401,9 @@ nsSelectUpdateTimer::~nsSelectUpdateTimer() //--------------------------------------------------------- -nsListControlFrame::nsListControlFrame() - : mWeakReferent(this) +nsListControlFrame::nsListControlFrame(nsIPresShell* aShell, + nsIDocument* aDocument) + : nsGfxScrollFrame(aShell, aDocument, PR_FALSE), mWeakReferent(this) { mComboboxFrame = nsnull; mButtonDown = PR_FALSE; @@ -464,7 +469,7 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext) if (IsInDropDownMode() == PR_FALSE) { nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } - return nsScrollFrame::Destroy(aPresContext); + return nsGfxScrollFrame::Destroy(aPresContext); } NS_IMETHODIMP @@ -533,7 +538,7 @@ nsListControlFrame::Paint(nsIPresContext* aPresContext, } } - return nsScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + return nsGfxScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } DO_GLOBAL_REFLOW_COUNT_DSP("nsListControlFrame", &aRenderingContext); @@ -541,6 +546,9 @@ nsListControlFrame::Paint(nsIPresContext* aPresContext, } +/* Note: this is called by the SelectsAreaFrame, which is the same + as the frame returned by GetOptionsContainer. It's the frame which is + scrolled by us. */ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer) { if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) return; @@ -557,7 +565,7 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer } nsIScrollableView * scrollableView; - GetScrollableView(scrollableView); + GetScrollableView(mPresContext, &scrollableView); if (!scrollableView) return; nsCOMPtr presShell; @@ -631,49 +639,18 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer if (NS_FAILED(result) || !childframe) return; - const nsIView * clippedView; - scrollableView->GetClipView(&clippedView); - if (!clippedView) return; - - nscoord x; - nscoord y; - scrollableView->GetScrollPosition(x,y); - // get the clipped rect - nsRect rect; - clippedView->GetBounds(rect); - - // now move it by the offset of the scroll position - rect.x = 0; - rect.y = 0; - rect.MoveBy(x,y); - // get the child rect nsRect fRect; childframe->GetRect(fRect); - - nsRect clipRect; - containerFrame->GetRect(clipRect); - clipRect.x = 0; - clipRect.y = 0; - - PRBool clipEmpty; - aRC.PushState(); - aRC.SetClipRect(clipRect, nsClipCombine_kReplace, clipEmpty); - - // adjust position is it is a child of a option group - if (focusedContent) { - nsRect optRect(0,0,0,0); - nsCOMPtr parentContent; - focusedContent->GetParent(*getter_AddRefs(parentContent)); - nsCOMPtr optGroup(do_QueryInterface(parentContent)); - if (optGroup) { - nsIFrame * optFrame; - result = presShell->GetPrimaryFrameFor(parentContent, &optFrame); - if (NS_SUCCEEDED(result) && optFrame) { - optFrame->GetRect(optRect); - } - } - fRect.y += optRect.y; + + // get it into the coordinates of containerFrame + nsIFrame* ancestor; + childframe->GetParent(&ancestor); + while (ancestor && ancestor != containerFrame) { + nsPoint pt; + ancestor->GetOrigin(pt); + fRect += pt; + ancestor->GetParent(&ancestor); } PRBool lastItemIsSelected = PR_FALSE; @@ -708,8 +685,6 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer innerRect.Deflate(nsSize(onePixelInTwips, onePixelInTwips)); nsCSSRendering::DrawDashedSides(0, aRC, dirty, borderStyle, colors, fRect, innerRect, 0, nsnull); - aRC.PopState(clipEmpty); - } //--------------------------------------------------------- @@ -732,19 +707,142 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) *aInstancePtr = (void *)((nsISelectControlFrame*)this); return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) { - *aInstancePtr = (void*)(nsIDOMMouseListener*) this; + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = + NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this)); + return NS_OK; + } + if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) { + *aInstancePtr = (void*)(nsIDOMMouseListener*) this; return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) { - *aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this; + if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) { + *aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this; return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) { - *aInstancePtr = (void*)(nsIDOMKeyListener*) this; + if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) { + *aInstancePtr = (void*)(nsIDOMKeyListener*) this; return NS_OK; } - return nsScrollFrame::QueryInterface(aIID, aInstancePtr); + return nsGfxScrollFrame::QueryInterface(aIID, aInstancePtr); +} + +//---------------------------------------------------------------------- +// nsIStatefulFrame +// These methods were originally in the nsScrollFrame superclass, +// but were moved here when nsListControlFrame switched to use +// nsGfxScrollFrame. +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::SaveState(nsIPresContext* aPresContext, + nsIPresState** aState) +{ + NS_ENSURE_ARG_POINTER(aState); + nsCOMPtr state; + nsresult res = NS_OK; + + nsIScrollableView* scrollingView; + GetScrollableView(aPresContext, &scrollingView); + + nscoord x = 0, y = 0; + if (scrollingView) { + scrollingView->GetScrollPosition(x, y); + } + + // Don't save scroll position if we are at (0,0) + if (x || y) { + nsIView* child = nsnull; + scrollingView->GetScrolledView(child); + NS_ENSURE_TRUE(child, NS_ERROR_FAILURE); + + nsRect childRect(0,0,0,0); + child->GetBounds(childRect); + + res = NS_NewPresState(getter_AddRefs(state)); + NS_ENSURE_SUCCESS(res, res); + + nsCOMPtr xoffset = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (xoffset) { + res = xoffset->SetData(x); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset); + } + + nsCOMPtr yoffset = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (yoffset) { + res = yoffset->SetData(y); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset); + } + + nsCOMPtr width = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (width) { + res = width->SetData(childRect.width); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width); + } + + nsCOMPtr height = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (height) { + res = height->SetData(childRect.height); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height); + } + *aState = state; + NS_ADDREF(*aState); + } + return res; +} + +//----------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::RestoreState(nsIPresContext* aPresContext, + nsIPresState* aState) +{ + NS_ENSURE_ARG_POINTER(aState); + + nsCOMPtr xoffset; + nsCOMPtr yoffset; + nsCOMPtr width; + nsCOMPtr height; + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height)); + + nsresult res = NS_ERROR_NULL_POINTER; + if (xoffset && yoffset) { + PRInt32 x,y,w,h; + res = xoffset->GetData(&x); + if (NS_SUCCEEDED(res)) + res = yoffset->GetData(&y); + if (NS_SUCCEEDED(res)) + res = width->GetData(&w); + if (NS_SUCCEEDED(res)) + res = height->GetData(&h); + + if (NS_SUCCEEDED(res)) { + nsIScrollableView* scrollingView; + GetScrollableView(aPresContext, &scrollingView); + if (scrollingView) { + nsIView* child = nsnull; + nsRect childRect(0,0,0,0); + if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) { + child->GetBounds(childRect); + } + x = (int)(((float)childRect.width / w) * x); + y = (int)(((float)childRect.height / h) * y); + + scrollingView->ScrollTo(x,y,0); + } + } + } + + return res; } #ifdef ACCESSIBILITY @@ -995,10 +1093,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, firstPassState.reason = eReflowReason_StyleChange; firstPassState.path = nsnull; } else { - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - aReflowState, - aStatus); + nsresult res = nsGfxScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + aReflowState, + aStatus); if (NS_FAILED(res)) { NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); @@ -1011,10 +1109,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } if (mPassId == 0 || mPassId == 1) { - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - firstPassState, - aStatus); + nsresult res = nsGfxScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + firstPassState, + aStatus); if (NS_FAILED(res)) { NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); @@ -1033,9 +1131,9 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // - // The nsScrollFrame::Reflow adds in the scrollbar width and border dimensions + // The nsGfxScrollFrame::Reflow adds in the scrollbar width and border dimensions // to the maxElementWidth, so these need to be subtracted - nscoord scrolledAreaWidth = scrolledAreaDesiredSize.mMaxElementWidth - + nscoord scrolledAreaWidth = scrolledAreaDesiredSize.width - (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height - (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); @@ -1048,19 +1146,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, PRBool isInDropDownMode = IsInDropDownMode(); nscoord visibleWidth = 0; - if (isInDropDownMode) { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - } + if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { + visibleWidth = scrolledAreaWidth; } else { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - } + visibleWidth = aReflowState.mComputedWidth; } // Determine if a scrollbar will be needed, If so we need to add @@ -1278,7 +1367,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, firstPassState.mComputedWidth = bidiScrolledAreaWidth; firstPassState.availableWidth = bidiScrolledAreaWidth; - nsScrollFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + nsGfxScrollFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); } #endif // IBMBIDI @@ -1289,7 +1378,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, secondPassState.reason = eReflowReason_Resize; if (mPassId == 0 || mPassId == 2) { - nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); + nsGfxScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); if (aReflowState.mComputedHeight == 0) { aDesiredSize.ascent = 0; aDesiredSize.descent = 0; @@ -1597,34 +1686,45 @@ nsListControlFrame::HandleListSelection(nsIDOMEvent* aEvent, NS_IMETHODIMP nsListControlFrame::CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents) { - - // get its view nsIView* view = nsnull; - GetView(aPresContext, &view); - nsCOMPtr viewMan; - PRBool result; + if (IsInDropDownMode()) { + GetView(aPresContext, &view); + } else { + nsIFrame* scrolledFrame = nsnull; + GetScrolledFrame(aPresContext, scrolledFrame); + NS_ASSERTION(scrolledFrame, "No scrolled frame found"); + NS_ENSURE_TRUE(scrolledFrame, NS_ERROR_FAILURE); + + nsIFrame* scrollport = nsnull; + scrolledFrame->GetParent(&scrollport); + NS_ASSERTION(scrollport, "No scrollport found"); + NS_ENSURE_TRUE(scrollport, NS_ERROR_FAILURE); - if (view) { - view->GetViewManager(*getter_AddRefs(viewMan)); - if (viewMan) { - if (aGrabMouseEvents) { - viewMan->GrabMouseEvents(view,result); - mIsCapturingMouseEvents = PR_TRUE; - } else { + scrollport->GetView(aPresContext, &view); + } + + NS_ASSERTION(view, "no view???"); + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); + + nsCOMPtr viewMan; + view->GetViewManager(*getter_AddRefs(viewMan)); + if (viewMan) { + PRBool result; + // It's not clear why we don't have the widget capture mouse events here. + if (aGrabMouseEvents) { + viewMan->GrabMouseEvents(view,result); + mIsCapturingMouseEvents = PR_TRUE; + } else { + nsIView* curGrabber; + viewMan->GetMouseEventGrabber(curGrabber); + if (curGrabber == view) { + // only unset the grabber if *we* are the ones doing the grabbing + // it could be a scrollbar inside this listbox which is actually grabbing + // This shouldn't be necessary. We should simply ensure that events targeting + // scrollbars are never visible to DOM consumers. viewMan->GrabMouseEvents(nsnull,result); - mIsCapturingMouseEvents = PR_FALSE; } - // XXX this is temp code -#if 0 - if (!mIsScrollbarVisible) { - nsIWidget * widget; - view->GetWidget(widget); - if (nsnull != widget) { - widget->CaptureMouse(aGrabMouseEvents); - NS_RELEASE(widget); - } - } -#endif + mIsCapturingMouseEvents = PR_FALSE; } } @@ -1682,7 +1782,7 @@ nsListControlFrame::HandleEvent(nsIPresContext* aPresContext, if (nsFormControlHelper::GetDisabled(mContent)) return NS_OK; - return nsScrollFrame::HandleEvent(aPresContext, aEvent, aEventStatus); + return nsGfxScrollFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } @@ -1701,7 +1801,7 @@ nsListControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mHasBeenInitialized = PR_FALSE; } } - nsresult rv = nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); + nsresult rv = nsGfxScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); // If all the content is here now check // to see if all the frames have been created @@ -1741,8 +1841,8 @@ nsListControlFrame::Init(nsIPresContext* aPresContext, { mPresContext = aPresContext; NS_ADDREF(mPresContext); - nsresult result = nsScrollFrame::Init(aPresContext, aContent, aParent, aContext, - aPrevInFlow); + nsresult result = nsGfxScrollFrame::Init(aPresContext, aContent, aParent, aContext, + aPrevInFlow); // get the receiver interface from the browser button's content node nsCOMPtr receiver(do_QueryInterface(mContent)); @@ -2387,7 +2487,7 @@ NS_IMETHODIMP nsListControlFrame::GetOptionsContainer(nsIPresContext* aPresContext, nsIFrame** aFrame) { - return FirstChild(aPresContext, nsnull, aFrame); + return GetScrolledFrame(aPresContext, *aFrame); } // Send out an onchange notification. @@ -2488,34 +2588,6 @@ nsListControlFrame::GetProperty(nsIAtom* aName, nsAString& aValue) return NS_OK; } - -//--------------------------------------------------------- -// Create a Borderless top level widget for drop-down lists. -nsresult -nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay) -{ - if (IsInDropDownMode() == PR_TRUE) { - nsCOMPtr vm; - aView->GetViewManager(*getter_AddRefs(vm)); - vm->SetViewFloating(aView, PR_TRUE); - - nsWidgetInitData widgetData; - widgetData.mWindowType = eWindowType_popup; - widgetData.mBorderStyle = eBorderStyle_default; - -#if defined(XP_MAC) || defined(XP_MACOSX) - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - aView->CreateWidget(kCPopUpCID, &widgetData, nsnull); -#else - static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); - aView->CreateWidget(kCChildCID, &widgetData, nsnull); -#endif - return NS_OK; - } else { - return nsScrollFrame::CreateScrollingViewWidget(aView, aDisplay); - } -} - //--------------------------------------------------------- void nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, @@ -2552,56 +2624,7 @@ nsListControlFrame::SyncViewWithFrame(nsIPresContext* aPresContext) // as if it were in it's normal position in the view hierarchy. mComboboxFrame->AbsolutelyPositionDropDown(); - nsPoint parentPos; - nsCOMPtr viewManager; - - //Get parent frame - nsIFrame* parent; - GetParentWithView(aPresContext, &parent); - NS_ASSERTION(parent, "GetParentWithView failed"); - - // Get parent view - nsIView* parentView = nsnull; - parent->GetView(aPresContext, &parentView); - - parentView->GetViewManager(*getter_AddRefs(viewManager)); - GetViewOffset(viewManager, parentView, parentPos); - nsIView* view = nsnull; - GetView(aPresContext, &view); - - nsIView* containingView = nsnull; - nsPoint offset; - GetOffsetFromView(aPresContext, offset, &containingView); - //nsSize size; - //GetSize(size); - - //nscoord width; - //nscoord height; - //view->GetDimensions(&width, &height); - - //if (width != mRect.width || height != mRect.height) { - //viewManager->ResizeView(view, mRect.width, mRect.height); - //} - nscoord x; - nscoord y; - view->GetPosition(&x, &y); - - nscoord newX = parentPos.x + offset.x; - nscoord newY = parentPos.y + offset.y; - - //if (newX != x || newY != y) { - viewManager->MoveViewTo(view, newX, newY); - //} - - nsViewVisibility visibility; - - view->GetVisibility(visibility); - const nsStyleVisibility* vis; - GetStyleData(eStyleStruct_Visibility, (const nsStyleStruct*&) vis); - - if (visibility != vis->mVisible) { - //view->SetVisibility(NS_STYLE_VISIBILITY_VISIBLE == disp->mVisible ?nsViewVisibility_kShow:nsViewVisibility_kHide); - } + nsContainerFrame::PositionFrameView(aPresContext, this); return NS_OK; } @@ -2647,35 +2670,6 @@ nsListControlFrame::AboutToRollup() return NS_OK; } -//--------------------------------------------------------- -nsresult -nsListControlFrame::GetScrollingParentView(nsIPresContext* aPresContext, - nsIFrame* aParent, - nsIView** aParentView) -{ - if (IsInDropDownMode() == PR_TRUE) { - // Use the parent frame to get the view manager - nsIView* parentView = nsnull; - nsresult rv = aParent->GetView(aPresContext, &parentView); - NS_ASSERTION(parentView, "GetView failed"); - nsCOMPtr viewManager; - parentView->GetViewManager(*getter_AddRefs(viewManager)); - NS_ASSERTION(viewManager, "GetViewManager failed"); - - // Ask the view manager for the root view and - // use it as the parent for popup scrolling lists. - // Using the normal view as the parent causes the - // drop-down list to be clipped to a parent view. - // Using the root view as the parent - // prevents this from happening. - viewManager->GetRootView(*aParentView); - NS_ASSERTION(aParentView, "GetRootView failed"); - return rv; - } else { - return nsScrollFrame::GetScrollingParentView(aPresContext, aParent, aParentView); - } -} - //--------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::DidReflow(nsIPresContext* aPresContext, @@ -2686,12 +2680,12 @@ nsListControlFrame::DidReflow(nsIPresContext* aPresContext, { //SyncViewWithFrame(); mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - nsresult rv = nsScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); + nsresult rv = nsGfxScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; SyncViewWithFrame(aPresContext); return rv; } else { - nsresult rv = nsScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); + nsresult rv = nsGfxScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); PRInt32 selectedIndex = mEndSelectionIndex; if (selectedIndex == kNothingSelected) { GetSelectedIndex(&selectedIndex); @@ -2710,12 +2704,12 @@ NS_IMETHODIMP nsListControlFrame::MoveTo(nsIPresContext* aPresContext, nscoord a { //SyncViewWithFrame(); mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - nsresult rv = nsScrollFrame::MoveTo(aPresContext, aX, aY); + nsresult rv = nsGfxScrollFrame::MoveTo(aPresContext, aX, aY); mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; //SyncViewWithFrame(); return rv; } else { - return nsScrollFrame::MoveTo(aPresContext, aX, aY); + return nsGfxScrollFrame::MoveTo(aPresContext, aX, aY); } } @@ -2980,17 +2974,6 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, return rv; } -void -nsListControlFrame::GetScrollableView(nsIScrollableView*& aScrollableView) -{ - aScrollableView = nsnull; - - nsIView * scrollView = nsnull; - GetView(mPresContext, &scrollView); - CallQueryInterface(scrollView, &aScrollableView); - NS_ASSERTION(aScrollableView, "We must be able to get a ScrollableView"); -} - //---------------------------------------------------------------------- nsresult nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) @@ -3081,6 +3064,12 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent) if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) { PerformSelection(selectedIndex, PR_FALSE, PR_FALSE); } + + // Make sure the SelectArea frame gets painted + // XXX this shouldn't be needed, but other places in this code do it + // and if we don't do this, invalidation doesn't happen when we move out + // of the top-level window. We should track this down and fix it --- roc + Invalidate(mPresContext, nsRect(0,0,mRect.width,mRect.height), PR_TRUE); } } else {// XXX - temporary until we get drag events if (mButtonDown) { @@ -3149,7 +3138,7 @@ nsresult nsListControlFrame::ScrollToFrame(nsIContent* aOptElement) { nsIScrollableView * scrollableView; - GetScrollableView(scrollableView); + GetScrollableView(mPresContext, &scrollableView); if (scrollableView) { // if null is passed in we scroll to 0,0 diff --git a/mozilla/layout/forms/nsListControlFrame.h b/mozilla/layout/forms/nsListControlFrame.h index 589a9facfdf..e82ed5a9862 100644 --- a/mozilla/layout/forms/nsListControlFrame.h +++ b/mozilla/layout/forms/nsListControlFrame.h @@ -48,10 +48,11 @@ //#define DO_PIXELS #endif -#include "nsScrollFrame.h" +#include "nsGfxScrollFrame.h" #include "nsIFormControlFrame.h" #include "nsIListControlFrame.h" #include "nsISelectControlFrame.h" +#include "nsIStatefulFrame.h" #include "nsIDOMMouseListener.h" #include "nsIDOMMouseMotionListener.h" #include "nsIDOMKeyListener.h" @@ -169,9 +170,10 @@ protected: * Frame-based listbox. */ -class nsListControlFrame : public nsScrollFrame, +class nsListControlFrame : public nsGfxScrollFrame, public nsIFormControlFrame, public nsIListControlFrame, + public nsIStatefulFrame, public nsIDOMMouseListener, public nsIDOMMouseMotionListener, public nsIDOMKeyListener, @@ -223,8 +225,6 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; - virtual PRBool SupportsVisibilityHidden() { return PR_FALSE; } - #ifdef DEBUG // nsIFrameDebug NS_IMETHOD GetFrameName(nsAString& aResult) const; @@ -290,6 +290,10 @@ public: NS_IMETHOD GetDummyFrame(nsIFrame** aFrame); NS_IMETHOD SetDummyFrame(nsIFrame* aFrame); + //nsIStatefulFrame + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + //nsIDOMEventListener NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent); NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent); @@ -339,16 +343,9 @@ protected: PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext); virtual void ResetList(nsIPresContext* aPresContext, nsVoidArray * aInxList = nsnull); - nsListControlFrame(); + nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument); virtual ~nsListControlFrame(); - // nsScrollFrame overrides - // Override the widget created for the list box so a Borderless top level - // widget is created for drop-down lists. - virtual nsresult CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay); - virtual nsresult GetScrollingParentView(nsIPresContext* aPresContext, - nsIFrame* aParent, - nsIView** aParentView); // Utility methods nsresult GetSizeAttribute(PRInt32 *aSize); nsIContent* GetOptionFromContent(nsIContent *aContent); @@ -361,7 +358,6 @@ protected: PRBool CheckIfAllFramesHere(); PRInt32 GetIndexFromContent(nsIContent *aContent); PRBool IsLeftButton(nsIDOMEvent* aMouseEvent); - void GetScrollableView(nsIScrollableView*& aScrollableView); // Dropped down stuff void SetComboboxItem(PRInt32 aIndex); diff --git a/mozilla/layout/forms/nsSelectsAreaFrame.cpp b/mozilla/layout/forms/nsSelectsAreaFrame.cpp index d067a84c871..23d9479644d 100644 --- a/mozilla/layout/forms/nsSelectsAreaFrame.cpp +++ b/mozilla/layout/forms/nsSelectsAreaFrame.cpp @@ -142,9 +142,18 @@ nsSelectsAreaFrame::Paint(nsIPresContext* aPresContext, PRUint32 aFlags) { nsresult rv = nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags); - // This assumes that that the ListControlFrame is the Parent - nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, mParent); - listFrame->PaintFocus(aRenderingContext, aWhichLayer); - return rv; + nsIFrame* frame = this; + while (frame) { + frame->GetParent(&frame); + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type == nsLayoutAtoms::listControlFrame) { + nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, frame); + listFrame->PaintFocus(aRenderingContext, aWhichLayer); + return NS_OK; + } + } + + return NS_OK; } diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index 24e9040184a..45dd3d2e4f7 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -3158,7 +3158,8 @@ nsTextControlFrame::GetWidthInCharacters() const } NS_IMETHODIMP -nsTextControlFrame::GetScrollableView(nsIScrollableView** aView) +nsTextControlFrame::GetScrollableView(nsIPresContext* aPresContext, + nsIScrollableView** aView) { nsresult rv = NS_OK; *aView = mScrollableView; diff --git a/mozilla/layout/forms/nsTextControlFrame.h b/mozilla/layout/forms/nsTextControlFrame.h index 88a88a61a95..21fc91427fb 100644 --- a/mozilla/layout/forms/nsTextControlFrame.h +++ b/mozilla/layout/forms/nsTextControlFrame.h @@ -287,7 +287,7 @@ protected: PRInt32 GetWidthInCharacters() const; // nsIScrollableViewProvider - NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + NS_IMETHOD GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView); private: //helper methods diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 3682590bfd9..34704541d7b 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -1175,10 +1175,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif -#ifdef DEBUG_roc - printf("*** Metrics width/height on the way out=%d,%d\n", aMetrics.width, aMetrics.height); -#endif - NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return rv; } diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index b173b99195a..dc2aa87a929 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -110,9 +110,7 @@ nsContainerFrame::SetInitialChildList(nsIPresContext* aPresContext, if (!mFrames.IsEmpty()) { // We already have child frames which means we've already been // initialized -#ifdef DEBUG_dbaron_off // XXX Fix asserts and remove this ifdef. NS_NOTREACHED("unexpected second call to SetInitialChildList"); -#endif result = NS_ERROR_UNEXPECTED; } else if (aListName) { // All we know about is the unnamed principal child list @@ -444,6 +442,10 @@ nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, // 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 is no longer needed; remove it!! + // 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 diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index a9359e3b359..a81063083c1 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -488,6 +488,53 @@ nsGfxScrollFrame::Init(nsIPresContext* aPresContext, mInner->mDocument->AddObserver(mInner); return rv; } + +void nsGfxScrollFrame::ReloadChildFrames(nsIPresContext* aPresContext) +{ + mInner->mScrollAreaBox = nsnull; + mInner->mHScrollbarBox = nsnull; + mInner->mVScrollbarBox = nsnull; + + nsIFrame* frame = nsnull; + FirstChild(aPresContext, nsnull, &frame); + while (frame) { + PRBool understood = PR_FALSE; + + nsIBox* box = nsnull; + frame->QueryInterface(NS_GET_IID(nsIBox), (void**)&box); + if (box) { + nsCOMPtr frameType; + frame->GetFrameType(getter_AddRefs(frameType)); + if (frameType == nsLayoutAtoms::scrollFrame) { + NS_ASSERTION(!mInner->mScrollAreaBox, "Found multiple scroll areas?"); + mInner->mScrollAreaBox = box; + understood = PR_TRUE; + } else { + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + if (content) { + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, + nsXULAtoms::orient, value)) { + // probably a scrollbar then + if (value.EqualsIgnoreCase("horizontal")) { + NS_ASSERTION(!mInner->mHScrollbarBox, "Found multiple horizontal scrollbars?"); + mInner->mHScrollbarBox = box; + } else { + NS_ASSERTION(!mInner->mVScrollbarBox, "Found multiple vertical scrollbars?"); + mInner->mVScrollbarBox = box; + } + understood = PR_TRUE; + } + } + } + } + + NS_ASSERTION(understood, "What is this frame doing here?"); + + frame->GetNextSibling(&frame); + } +} NS_IMETHODIMP nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, @@ -496,15 +543,8 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, { nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); - // get scroll area - GetChildBox(&mInner->mScrollAreaBox); - - // horizontal scrollbar - mInner->mScrollAreaBox->GetNextBox(&mInner->mHScrollbarBox); - // vertical scrollbar - if (mInner->mHScrollbarBox) - mInner->mHScrollbarBox->GetNextBox(&mInner->mVScrollbarBox); + ReloadChildFrames(aPresContext); // listen for scroll events. mInner->GetScrollableView(aPresContext)->AddScrollPositionListener(mInner); @@ -519,12 +559,12 @@ nsGfxScrollFrame::AppendFrames(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - return frame->AppendFrames(aPresContext, - aPresShell, - aListName, - aFrameList); + nsresult rv = nsBoxFrame::AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); + ReloadChildFrames(aPresContext); + return rv; } NS_IMETHODIMP @@ -534,14 +574,13 @@ nsGfxScrollFrame::InsertFrames(nsIPresContext* aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->InsertFrames(aPresContext, - aPresShell, - aListName, - aPrevFrame, - aFrameList); + nsresult rv = nsBoxFrame::InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); + ReloadChildFrames(aPresContext); + return rv; } NS_IMETHODIMP @@ -550,30 +589,12 @@ nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - nsIFrame* vscroll = nsnull; - if (mInner->mVScrollbarBox) - mInner->mVScrollbarBox->GetFrame(&vscroll); - nsIFrame* hscroll = nsnull; - if (mInner->mHScrollbarBox) - mInner->mHScrollbarBox->GetFrame(&hscroll); - - if (aOldFrame == vscroll) { - mInner->mVScrollbarBox = nsnull; - return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - } - else if (aOldFrame == hscroll) { - mInner->mHScrollbarBox = nsnull; - return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - } - else { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->RemoveFrame (aPresContext, - aPresShell, - aListName, - aOldFrame); - } + nsresult rv = nsBoxFrame::RemoveFrame(aPresContext, + aPresShell, + aListName, + aOldFrame); + ReloadChildFrames(aPresContext); + return rv; } @@ -584,14 +605,13 @@ nsGfxScrollFrame::ReplaceFrame(nsIPresContext* aPresContext, nsIFrame* aOldFrame, nsIFrame* aNewFrame) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->ReplaceFrame (aPresContext, - aPresShell, - aListName, - aOldFrame, - aNewFrame); + nsresult rv = nsBoxFrame::ReplaceFrame(aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); + ReloadChildFrames(aPresContext); + return rv; } @@ -892,6 +912,7 @@ NS_INTERFACE_MAP_BEGIN(nsGfxScrollFrame) NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) #endif NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame) + NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider) NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) @@ -1078,11 +1099,13 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, nsIScrollableView* nsGfxScrollFrameInner::GetScrollableView(nsIPresContext* aPresContext) { - nsIScrollableView* scrollingView; nsIView* view; nsIFrame* frame = nsnull; mScrollAreaBox->GetFrame(&frame); frame->GetView(aPresContext, &view); + if (!view) return nsnull; + + nsIScrollableView* scrollingView; nsresult result = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollingView); NS_ASSERTION(NS_SUCCEEDED(result), "assertion gfx scrollframe does not contain a scrollframe"); return scrollingView; diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index 5b0a31932a4..88c44b7d0b4 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -69,10 +69,8 @@ public: virtual ~nsGfxScrollFrame(); - - // 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 + // Called to set the child frames. We typically have three: the scroll area, + // the vertical scrollbar, and the horizontal scrollbar. NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); @@ -184,6 +182,10 @@ protected: nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot); virtual PRIntn GetSkipSides() const; + // If a child frame was added or removed, reload our child frame list + // We need this if a scrollbar frame is recreated + void ReloadChildFrames(nsIPresContext* aPresContext); + private: friend class nsGfxScrollFrameInner; nsGfxScrollFrameInner* mInner; diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.cpp b/mozilla/layout/generic/nsHTMLContainerFrame.cpp index 27e5f988b7d..8814a071f5e 100644 --- a/mozilla/layout/generic/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/generic/nsHTMLContainerFrame.cpp @@ -378,29 +378,23 @@ ReparentFrameViewTo(nsIPresContext* aPresContext, // XXX Pretend this view is last of the parent's views in document order aViewManager->InsertChild(aNewParentView, view, nsnull, PR_TRUE); } else { - // Iterate the child frames, and check each child frame to see if it has - // a view - nsIFrame* childFrame; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } - - // Also check the overflow-list - aFrame->FirstChild(aPresContext, nsLayoutAtoms::overflowList, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } - - // Also check the floater-list - aFrame->FirstChild(aPresContext, nsLayoutAtoms::floaterList, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } + PRInt32 listIndex = 0; + nsCOMPtr listName; + // This loop iterates through every child list name, and also + // executes once with listName == nsnull. + do { + aFrame->GetAdditionalChildListName(listIndex, getter_AddRefs(listName)); + listIndex++; + // Iterate the child frames, and check each child frame to see if it has + // a view + nsIFrame* childFrame; + aFrame->FirstChild(aPresContext, listName, &childFrame); + for (; childFrame; childFrame->GetNextSibling(&childFrame)) { + ReparentFrameViewTo(aPresContext, childFrame, aViewManager, + aNewParentView, aOldParentView); + } + } while (listName); } return NS_OK; diff --git a/mozilla/layout/generic/nsIScrollableFrame.h b/mozilla/layout/generic/nsIScrollableFrame.h index 8682d7cdf45..67e90c6275b 100644 --- a/mozilla/layout/generic/nsIScrollableFrame.h +++ b/mozilla/layout/generic/nsIScrollableFrame.h @@ -41,6 +41,7 @@ #include "nsISupports.h" #include "nsCoord.h" #include "nsIViewManager.h" +#include "nsIScrollableViewProvider.h" class nsIFrame; class nsIBox; @@ -51,7 +52,7 @@ class nsIPresContext; { 0xc95f1831, 0xc372, 0x11d1, \ { 0xb7, 0x21, 0x0, 0x64, 0x9, 0x92, 0xd8, 0xc9 } } -class nsIScrollableFrame : public nsISupports { +class nsIScrollableFrame : public nsIScrollableViewProvider { public: enum nsScrollPref { diff --git a/mozilla/layout/generic/nsIScrollableViewProvider.h b/mozilla/layout/generic/nsIScrollableViewProvider.h index 622a7cacbf6..e2ea88323f6 100644 --- a/mozilla/layout/generic/nsIScrollableViewProvider.h +++ b/mozilla/layout/generic/nsIScrollableViewProvider.h @@ -37,7 +37,7 @@ class nsIScrollableViewProvider : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEWPROVIDER_IID) - NS_IMETHOD GetScrollableView(nsIScrollableView** aView)=0; + NS_IMETHOD GetScrollableView(nsIPresContext* aContext, nsIScrollableView** aResult)=0; }; #endif /* _nsIScrollableViewProvider_h */ diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 3682590bfd9..34704541d7b 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -1175,10 +1175,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } #endif -#ifdef DEBUG_roc - printf("*** Metrics width/height on the way out=%d,%d\n", aMetrics.width, aMetrics.height); -#endif - NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return rv; } diff --git a/mozilla/layout/html/base/src/nsContainerFrame.cpp b/mozilla/layout/html/base/src/nsContainerFrame.cpp index b173b99195a..dc2aa87a929 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsContainerFrame.cpp @@ -110,9 +110,7 @@ nsContainerFrame::SetInitialChildList(nsIPresContext* aPresContext, if (!mFrames.IsEmpty()) { // We already have child frames which means we've already been // initialized -#ifdef DEBUG_dbaron_off // XXX Fix asserts and remove this ifdef. NS_NOTREACHED("unexpected second call to SetInitialChildList"); -#endif result = NS_ERROR_UNEXPECTED; } else if (aListName) { // All we know about is the unnamed principal child list @@ -444,6 +442,10 @@ nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, // 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 is no longer needed; remove it!! + // 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 diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index b1b1d78c428..96fcfae8719 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -2389,9 +2389,17 @@ FrameManager::GenerateStateKey(nsIContent* aContent, // Hash by index of control in doc (we are not in a form) // These are important as they are unique, and type/name may not be. + + // We don't refresh the form control list here (passing PR_TRUE + // for aFlush), although we really should. Forcing a flush + // causes a signficant pageload performance hit. See bug + // 166636. Doing this wrong means you will see the assertion + // below being hit. mHTMLFormControls->IndexOf(aContent, index, PR_FALSE); NS_ASSERTION(index > -1, - "nsFrameManager::GenerateStateKey didn't find content by type!"); + "nsFrameManager::GenerateStateKey didn't find content " + "by type! See bug 139568"); + if (index > -1) { KeyAppendInt(index, aKey); generatedUniqueKey = PR_TRUE; diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index a9359e3b359..a81063083c1 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -488,6 +488,53 @@ nsGfxScrollFrame::Init(nsIPresContext* aPresContext, mInner->mDocument->AddObserver(mInner); return rv; } + +void nsGfxScrollFrame::ReloadChildFrames(nsIPresContext* aPresContext) +{ + mInner->mScrollAreaBox = nsnull; + mInner->mHScrollbarBox = nsnull; + mInner->mVScrollbarBox = nsnull; + + nsIFrame* frame = nsnull; + FirstChild(aPresContext, nsnull, &frame); + while (frame) { + PRBool understood = PR_FALSE; + + nsIBox* box = nsnull; + frame->QueryInterface(NS_GET_IID(nsIBox), (void**)&box); + if (box) { + nsCOMPtr frameType; + frame->GetFrameType(getter_AddRefs(frameType)); + if (frameType == nsLayoutAtoms::scrollFrame) { + NS_ASSERTION(!mInner->mScrollAreaBox, "Found multiple scroll areas?"); + mInner->mScrollAreaBox = box; + understood = PR_TRUE; + } else { + nsCOMPtr content; + frame->GetContent(getter_AddRefs(content)); + if (content) { + nsAutoString value; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttr(kNameSpaceID_None, + nsXULAtoms::orient, value)) { + // probably a scrollbar then + if (value.EqualsIgnoreCase("horizontal")) { + NS_ASSERTION(!mInner->mHScrollbarBox, "Found multiple horizontal scrollbars?"); + mInner->mHScrollbarBox = box; + } else { + NS_ASSERTION(!mInner->mVScrollbarBox, "Found multiple vertical scrollbars?"); + mInner->mVScrollbarBox = box; + } + understood = PR_TRUE; + } + } + } + } + + NS_ASSERTION(understood, "What is this frame doing here?"); + + frame->GetNextSibling(&frame); + } +} NS_IMETHODIMP nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, @@ -496,15 +543,8 @@ nsGfxScrollFrame::SetInitialChildList(nsIPresContext* aPresContext, { nsresult rv = nsBoxFrame::SetInitialChildList(aPresContext, aListName, aChildList); - // get scroll area - GetChildBox(&mInner->mScrollAreaBox); - - // horizontal scrollbar - mInner->mScrollAreaBox->GetNextBox(&mInner->mHScrollbarBox); - // vertical scrollbar - if (mInner->mHScrollbarBox) - mInner->mHScrollbarBox->GetNextBox(&mInner->mVScrollbarBox); + ReloadChildFrames(aPresContext); // listen for scroll events. mInner->GetScrollableView(aPresContext)->AddScrollPositionListener(mInner); @@ -519,12 +559,12 @@ nsGfxScrollFrame::AppendFrames(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - return frame->AppendFrames(aPresContext, - aPresShell, - aListName, - aFrameList); + nsresult rv = nsBoxFrame::AppendFrames(aPresContext, + aPresShell, + aListName, + aFrameList); + ReloadChildFrames(aPresContext); + return rv; } NS_IMETHODIMP @@ -534,14 +574,13 @@ nsGfxScrollFrame::InsertFrames(nsIPresContext* aPresContext, nsIFrame* aPrevFrame, nsIFrame* aFrameList) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->InsertFrames(aPresContext, - aPresShell, - aListName, - aPrevFrame, - aFrameList); + nsresult rv = nsBoxFrame::InsertFrames(aPresContext, + aPresShell, + aListName, + aPrevFrame, + aFrameList); + ReloadChildFrames(aPresContext); + return rv; } NS_IMETHODIMP @@ -550,30 +589,12 @@ nsGfxScrollFrame::RemoveFrame(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - nsIFrame* vscroll = nsnull; - if (mInner->mVScrollbarBox) - mInner->mVScrollbarBox->GetFrame(&vscroll); - nsIFrame* hscroll = nsnull; - if (mInner->mHScrollbarBox) - mInner->mHScrollbarBox->GetFrame(&hscroll); - - if (aOldFrame == vscroll) { - mInner->mVScrollbarBox = nsnull; - return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - } - else if (aOldFrame == hscroll) { - mInner->mHScrollbarBox = nsnull; - return nsBoxFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); - } - else { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->RemoveFrame (aPresContext, - aPresShell, - aListName, - aOldFrame); - } + nsresult rv = nsBoxFrame::RemoveFrame(aPresContext, + aPresShell, + aListName, + aOldFrame); + ReloadChildFrames(aPresContext); + return rv; } @@ -584,14 +605,13 @@ nsGfxScrollFrame::ReplaceFrame(nsIPresContext* aPresContext, nsIFrame* aOldFrame, nsIFrame* aNewFrame) { - nsIFrame* frame; - mInner->mScrollAreaBox->GetFrame(&frame); - - return frame->ReplaceFrame (aPresContext, - aPresShell, - aListName, - aOldFrame, - aNewFrame); + nsresult rv = nsBoxFrame::ReplaceFrame(aPresContext, + aPresShell, + aListName, + aOldFrame, + aNewFrame); + ReloadChildFrames(aPresContext); + return rv; } @@ -892,6 +912,7 @@ NS_INTERFACE_MAP_BEGIN(nsGfxScrollFrame) NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) #endif NS_INTERFACE_MAP_ENTRY(nsIScrollableFrame) + NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider) NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) @@ -1078,11 +1099,13 @@ nsGfxScrollFrameInner::AttributeChanged(nsIDocument *aDocument, nsIScrollableView* nsGfxScrollFrameInner::GetScrollableView(nsIPresContext* aPresContext) { - nsIScrollableView* scrollingView; nsIView* view; nsIFrame* frame = nsnull; mScrollAreaBox->GetFrame(&frame); frame->GetView(aPresContext, &view); + if (!view) return nsnull; + + nsIScrollableView* scrollingView; nsresult result = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollingView); NS_ASSERTION(NS_SUCCEEDED(result), "assertion gfx scrollframe does not contain a scrollframe"); return scrollingView; diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.h b/mozilla/layout/html/base/src/nsGfxScrollFrame.h index 5b0a31932a4..88c44b7d0b4 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.h +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.h @@ -69,10 +69,8 @@ public: virtual ~nsGfxScrollFrame(); - - // 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 + // Called to set the child frames. We typically have three: the scroll area, + // the vertical scrollbar, and the horizontal scrollbar. NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); @@ -184,6 +182,10 @@ protected: nsGfxScrollFrame(nsIPresShell* aShell, nsIDocument* aDocument, PRBool aIsRoot); virtual PRIntn GetSkipSides() const; + // If a child frame was added or removed, reload our child frame list + // We need this if a scrollbar frame is recreated + void ReloadChildFrames(nsIPresContext* aPresContext); + private: friend class nsGfxScrollFrameInner; nsGfxScrollFrameInner* mInner; diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp index 27e5f988b7d..8814a071f5e 100644 --- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp @@ -378,29 +378,23 @@ ReparentFrameViewTo(nsIPresContext* aPresContext, // XXX Pretend this view is last of the parent's views in document order aViewManager->InsertChild(aNewParentView, view, nsnull, PR_TRUE); } else { - // Iterate the child frames, and check each child frame to see if it has - // a view - nsIFrame* childFrame; - aFrame->FirstChild(aPresContext, nsnull, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } - - // Also check the overflow-list - aFrame->FirstChild(aPresContext, nsLayoutAtoms::overflowList, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } - - // Also check the floater-list - aFrame->FirstChild(aPresContext, nsLayoutAtoms::floaterList, &childFrame); - while (childFrame) { - ReparentFrameViewTo(aPresContext, childFrame, aViewManager, aNewParentView, aOldParentView); - childFrame->GetNextSibling(&childFrame); - } + PRInt32 listIndex = 0; + nsCOMPtr listName; + // This loop iterates through every child list name, and also + // executes once with listName == nsnull. + do { + aFrame->GetAdditionalChildListName(listIndex, getter_AddRefs(listName)); + listIndex++; + // Iterate the child frames, and check each child frame to see if it has + // a view + nsIFrame* childFrame; + aFrame->FirstChild(aPresContext, listName, &childFrame); + for (; childFrame; childFrame->GetNextSibling(&childFrame)) { + ReparentFrameViewTo(aPresContext, childFrame, aViewManager, + aNewParentView, aOldParentView); + } + } while (listName); } return NS_OK; diff --git a/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp b/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp index d067a84c871..23d9479644d 100644 --- a/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp +++ b/mozilla/layout/html/base/src/nsSelectsAreaFrame.cpp @@ -142,9 +142,18 @@ nsSelectsAreaFrame::Paint(nsIPresContext* aPresContext, PRUint32 aFlags) { nsresult rv = nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags); - // This assumes that that the ListControlFrame is the Parent - nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, mParent); - listFrame->PaintFocus(aRenderingContext, aWhichLayer); - return rv; + nsIFrame* frame = this; + while (frame) { + frame->GetParent(&frame); + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type == nsLayoutAtoms::listControlFrame) { + nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, frame); + listFrame->PaintFocus(aRenderingContext, aWhichLayer); + return NS_OK; + } + } + + return NS_OK; } diff --git a/mozilla/layout/html/document/src/forms.css b/mozilla/layout/html/document/src/forms.css index 7062def52c7..a6651d749de 100644 --- a/mozilla/layout/html/document/src/forms.css +++ b/mozilla/layout/html/document/src/forms.css @@ -171,11 +171,8 @@ select > input[type="button"]:active { background-image: url("arrowd.gif") !important; } -select[size], :-moz-select-scrolled-content { - overflow: -moz-scrollbars-vertical; -} - select[size] { + overflow: -moz-scrollbars-vertical; -moz-appearance: listbox; } @@ -239,7 +236,7 @@ optgroup:before { background-color: inherit; -moz-user-select: none; - border: 1px outset black !important; + border: 1px outset black !important; } input[disabled], diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index ea676373a57..40fb579e769 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -756,7 +756,7 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, // move the dropdown list up dropdownYOffset = - (dropdownRect.height); } - } + } dropdownRect.x = 0; dropdownRect.y = dropdownYOffset; @@ -764,10 +764,6 @@ nsComboboxControlFrame::PositionDropdown(nsIPresContext* aPresContext, mDropdownFrame->GetRect(currentRect); mDropdownFrame->SetRect(aPresContext, dropdownRect); -#ifdef DEBUG_rodsXXXXXX - printf("%d Position Dropdown at: %d %d %d %d\n", counter++, dropdownRect.x, dropdownRect.y, dropdownRect.width, dropdownRect.height); -#endif - return rv; } @@ -1594,8 +1590,15 @@ nsComboboxControlFrame::Reflow(nsIPresContext* aPresContext, REFLOW_DEBUG_MSG("Unconstrained.....\n"); REFLOW_DEBUG_MSG4("*B mItemDisplayWidth %d dropdownRect.width:%d dropdownRect.w+h %d\n", PX(mItemDisplayWidth), PX(dropdownRect.width), PX((dropBorderPadding.left + dropBorderPadding.right))); - // Start with the dropdown rect's width - mItemDisplayWidth = dropdownRect.width; + // Start with the dropdown rect's width (at this stage, it's the + // natural width of the content in the list, i.e., the width of + // the widest content, i.e. the preferred width for the display + // frame) and add room for the button, which is assumed to match + // the width of the scrollbar (note that the scrollbarWidth is + // passed as aBtnWidth to ReflowCombobox). (When the dropdown was + // an nsScrollFrame the scrollbar width seems to have already been + // added to its unconstrained width.) + mItemDisplayWidth = dropdownRect.width + scrollbarWidth; REFLOW_DEBUG_MSG2("* mItemDisplayWidth %d\n", PX(mItemDisplayWidth)); @@ -2584,18 +2587,20 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, //nsIScrollableViewProvider //---------------------------------------------------------------------- NS_METHOD -nsComboboxControlFrame::GetScrollableView(nsIScrollableView** aView) +nsComboboxControlFrame::GetScrollableView(nsIPresContext* aPresContext, + nsIScrollableView** aView) { *aView = nsnull; - nsIView* view = nsnull; - mDropdownFrame->GetView(mPresContext, &view); - if (view) { - nsIScrollableView* sv = nsnull; - nsresult rv = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**) &sv); - if (NS_SUCCEEDED(rv) && sv) - *aView = sv; - } - return NS_OK; + + if (!mDropdownFrame) + return NS_ERROR_FAILURE; + + nsIScrollableFrame* scrollable = nsnull; + nsresult rv = CallQueryInterface(mDropdownFrame, &scrollable); + if (NS_FAILED(rv)) + return rv; + + return scrollable->GetScrollableView(aPresContext, aView); } //--------------------------------------------------------- diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 6057ab3eb6f..144378364cd 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -212,7 +212,7 @@ public: { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! // nsIScrollableViewProvider - NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + NS_IMETHOD GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView); //nsIStatefulFrame NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index be91a5f54aa..75bce68414b 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -46,6 +46,8 @@ #include "nsIHTMLContent.h" #include "nsIFormControl.h" #include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLOptionsCollection.h" #include "nsIDOMNSHTMLOptionCollectn.h" #include "nsIDOMHTMLSelectElement.h" @@ -117,7 +119,9 @@ NS_NewListControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsListControlFrame* it = new (aPresShell) nsListControlFrame; + nsCOMPtr doc; + aPresShell->GetDocument(getter_AddRefs(doc)); + nsListControlFrame* it = new (aPresShell) nsListControlFrame(aPresShell, doc); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } @@ -397,8 +401,9 @@ nsSelectUpdateTimer::~nsSelectUpdateTimer() //--------------------------------------------------------- -nsListControlFrame::nsListControlFrame() - : mWeakReferent(this) +nsListControlFrame::nsListControlFrame(nsIPresShell* aShell, + nsIDocument* aDocument) + : nsGfxScrollFrame(aShell, aDocument, PR_FALSE), mWeakReferent(this) { mComboboxFrame = nsnull; mButtonDown = PR_FALSE; @@ -464,7 +469,7 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext) if (IsInDropDownMode() == PR_FALSE) { nsFormControlFrame::RegUnRegAccessKey(aPresContext, NS_STATIC_CAST(nsIFrame*, this), PR_FALSE); } - return nsScrollFrame::Destroy(aPresContext); + return nsGfxScrollFrame::Destroy(aPresContext); } NS_IMETHODIMP @@ -533,7 +538,7 @@ nsListControlFrame::Paint(nsIPresContext* aPresContext, } } - return nsScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + return nsGfxScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } DO_GLOBAL_REFLOW_COUNT_DSP("nsListControlFrame", &aRenderingContext); @@ -541,6 +546,9 @@ nsListControlFrame::Paint(nsIPresContext* aPresContext, } +/* Note: this is called by the SelectsAreaFrame, which is the same + as the frame returned by GetOptionsContainer. It's the frame which is + scrolled by us. */ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer) { if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) return; @@ -557,7 +565,7 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer } nsIScrollableView * scrollableView; - GetScrollableView(scrollableView); + GetScrollableView(mPresContext, &scrollableView); if (!scrollableView) return; nsCOMPtr presShell; @@ -631,49 +639,18 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer if (NS_FAILED(result) || !childframe) return; - const nsIView * clippedView; - scrollableView->GetClipView(&clippedView); - if (!clippedView) return; - - nscoord x; - nscoord y; - scrollableView->GetScrollPosition(x,y); - // get the clipped rect - nsRect rect; - clippedView->GetBounds(rect); - - // now move it by the offset of the scroll position - rect.x = 0; - rect.y = 0; - rect.MoveBy(x,y); - // get the child rect nsRect fRect; childframe->GetRect(fRect); - - nsRect clipRect; - containerFrame->GetRect(clipRect); - clipRect.x = 0; - clipRect.y = 0; - - PRBool clipEmpty; - aRC.PushState(); - aRC.SetClipRect(clipRect, nsClipCombine_kReplace, clipEmpty); - - // adjust position is it is a child of a option group - if (focusedContent) { - nsRect optRect(0,0,0,0); - nsCOMPtr parentContent; - focusedContent->GetParent(*getter_AddRefs(parentContent)); - nsCOMPtr optGroup(do_QueryInterface(parentContent)); - if (optGroup) { - nsIFrame * optFrame; - result = presShell->GetPrimaryFrameFor(parentContent, &optFrame); - if (NS_SUCCEEDED(result) && optFrame) { - optFrame->GetRect(optRect); - } - } - fRect.y += optRect.y; + + // get it into the coordinates of containerFrame + nsIFrame* ancestor; + childframe->GetParent(&ancestor); + while (ancestor && ancestor != containerFrame) { + nsPoint pt; + ancestor->GetOrigin(pt); + fRect += pt; + ancestor->GetParent(&ancestor); } PRBool lastItemIsSelected = PR_FALSE; @@ -708,8 +685,6 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer innerRect.Deflate(nsSize(onePixelInTwips, onePixelInTwips)); nsCSSRendering::DrawDashedSides(0, aRC, dirty, borderStyle, colors, fRect, innerRect, 0, nsnull); - aRC.PopState(clipEmpty); - } //--------------------------------------------------------- @@ -732,19 +707,142 @@ nsListControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) *aInstancePtr = (void *)((nsISelectControlFrame*)this); return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) { - *aInstancePtr = (void*)(nsIDOMMouseListener*) this; + if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = + NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIStatefulFrame*,this)); + return NS_OK; + } + if (aIID.Equals(NS_GET_IID(nsIDOMMouseListener))) { + *aInstancePtr = (void*)(nsIDOMMouseListener*) this; return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) { - *aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this; + if (aIID.Equals(NS_GET_IID(nsIDOMMouseMotionListener))) { + *aInstancePtr = (void*)(nsIDOMMouseMotionListener*) this; return NS_OK; } - if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) { - *aInstancePtr = (void*)(nsIDOMKeyListener*) this; + if (aIID.Equals(NS_GET_IID(nsIDOMKeyListener))) { + *aInstancePtr = (void*)(nsIDOMKeyListener*) this; return NS_OK; } - return nsScrollFrame::QueryInterface(aIID, aInstancePtr); + return nsGfxScrollFrame::QueryInterface(aIID, aInstancePtr); +} + +//---------------------------------------------------------------------- +// nsIStatefulFrame +// These methods were originally in the nsScrollFrame superclass, +// but were moved here when nsListControlFrame switched to use +// nsGfxScrollFrame. +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::SaveState(nsIPresContext* aPresContext, + nsIPresState** aState) +{ + NS_ENSURE_ARG_POINTER(aState); + nsCOMPtr state; + nsresult res = NS_OK; + + nsIScrollableView* scrollingView; + GetScrollableView(aPresContext, &scrollingView); + + nscoord x = 0, y = 0; + if (scrollingView) { + scrollingView->GetScrollPosition(x, y); + } + + // Don't save scroll position if we are at (0,0) + if (x || y) { + nsIView* child = nsnull; + scrollingView->GetScrolledView(child); + NS_ENSURE_TRUE(child, NS_ERROR_FAILURE); + + nsRect childRect(0,0,0,0); + child->GetBounds(childRect); + + res = NS_NewPresState(getter_AddRefs(state)); + NS_ENSURE_SUCCESS(res, res); + + nsCOMPtr xoffset = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (xoffset) { + res = xoffset->SetData(x); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), xoffset); + } + + nsCOMPtr yoffset = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (yoffset) { + res = yoffset->SetData(y); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), yoffset); + } + + nsCOMPtr width = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (width) { + res = width->SetData(childRect.width); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("width"), width); + } + + nsCOMPtr height = + do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID, &res); + if (height) { + res = height->SetData(childRect.height); + NS_ENSURE_SUCCESS(res, res); + state->SetStatePropertyAsSupports(NS_LITERAL_STRING("height"), height); + } + *aState = state; + NS_ADDREF(*aState); + } + return res; +} + +//----------------------------------------------------------- +NS_IMETHODIMP +nsListControlFrame::RestoreState(nsIPresContext* aPresContext, + nsIPresState* aState) +{ + NS_ENSURE_ARG_POINTER(aState); + + nsCOMPtr xoffset; + nsCOMPtr yoffset; + nsCOMPtr width; + nsCOMPtr height; + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("x-offset"), getter_AddRefs(xoffset)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("y-offset"), getter_AddRefs(yoffset)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("width"), getter_AddRefs(width)); + aState->GetStatePropertyAsSupports(NS_LITERAL_STRING("height"), getter_AddRefs(height)); + + nsresult res = NS_ERROR_NULL_POINTER; + if (xoffset && yoffset) { + PRInt32 x,y,w,h; + res = xoffset->GetData(&x); + if (NS_SUCCEEDED(res)) + res = yoffset->GetData(&y); + if (NS_SUCCEEDED(res)) + res = width->GetData(&w); + if (NS_SUCCEEDED(res)) + res = height->GetData(&h); + + if (NS_SUCCEEDED(res)) { + nsIScrollableView* scrollingView; + GetScrollableView(aPresContext, &scrollingView); + if (scrollingView) { + nsIView* child = nsnull; + nsRect childRect(0,0,0,0); + if (NS_SUCCEEDED(scrollingView->GetScrolledView(child)) && child) { + child->GetBounds(childRect); + } + x = (int)(((float)childRect.width / w) * x); + y = (int)(((float)childRect.height / h) * y); + + scrollingView->ScrollTo(x,y,0); + } + } + } + + return res; } #ifdef ACCESSIBILITY @@ -995,10 +1093,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, firstPassState.reason = eReflowReason_StyleChange; firstPassState.path = nsnull; } else { - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - aReflowState, - aStatus); + nsresult res = nsGfxScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + aReflowState, + aStatus); if (NS_FAILED(res)) { NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); @@ -1011,10 +1109,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, } if (mPassId == 0 || mPassId == 1) { - nsresult res = nsScrollFrame::Reflow(aPresContext, - scrolledAreaDesiredSize, - firstPassState, - aStatus); + nsresult res = nsGfxScrollFrame::Reflow(aPresContext, + scrolledAreaDesiredSize, + firstPassState, + aStatus); if (NS_FAILED(res)) { NS_ASSERTION(aDesiredSize.width < 100000, "Width is still NS_UNCONSTRAINEDSIZE"); NS_ASSERTION(aDesiredSize.height < 100000, "Height is still NS_UNCONSTRAINEDSIZE"); @@ -1033,9 +1131,9 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, // Compute the bounding box of the contents of the list using the area // calculated by the first reflow as a starting point. // - // The nsScrollFrame::Reflow adds in the scrollbar width and border dimensions + // The nsGfxScrollFrame::Reflow adds in the scrollbar width and border dimensions // to the maxElementWidth, so these need to be subtracted - nscoord scrolledAreaWidth = scrolledAreaDesiredSize.mMaxElementWidth - + nscoord scrolledAreaWidth = scrolledAreaDesiredSize.width - (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right); nscoord scrolledAreaHeight = scrolledAreaDesiredSize.height - (aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom); @@ -1048,19 +1146,10 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, PRBool isInDropDownMode = IsInDropDownMode(); nscoord visibleWidth = 0; - if (isInDropDownMode) { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - visibleWidth -= aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - } + if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { + visibleWidth = scrolledAreaWidth; } else { - if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) { - visibleWidth = scrolledAreaWidth; - } else { - visibleWidth = aReflowState.mComputedWidth; - } + visibleWidth = aReflowState.mComputedWidth; } // Determine if a scrollbar will be needed, If so we need to add @@ -1278,7 +1367,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, firstPassState.mComputedWidth = bidiScrolledAreaWidth; firstPassState.availableWidth = bidiScrolledAreaWidth; - nsScrollFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); + nsGfxScrollFrame::Reflow(aPresContext, aDesiredSize, firstPassState, aStatus); } #endif // IBMBIDI @@ -1289,7 +1378,7 @@ nsListControlFrame::Reflow(nsIPresContext* aPresContext, secondPassState.reason = eReflowReason_Resize; if (mPassId == 0 || mPassId == 2) { - nsScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); + nsGfxScrollFrame::Reflow(aPresContext, aDesiredSize, secondPassState, aStatus); if (aReflowState.mComputedHeight == 0) { aDesiredSize.ascent = 0; aDesiredSize.descent = 0; @@ -1597,34 +1686,45 @@ nsListControlFrame::HandleListSelection(nsIDOMEvent* aEvent, NS_IMETHODIMP nsListControlFrame::CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents) { - - // get its view nsIView* view = nsnull; - GetView(aPresContext, &view); - nsCOMPtr viewMan; - PRBool result; + if (IsInDropDownMode()) { + GetView(aPresContext, &view); + } else { + nsIFrame* scrolledFrame = nsnull; + GetScrolledFrame(aPresContext, scrolledFrame); + NS_ASSERTION(scrolledFrame, "No scrolled frame found"); + NS_ENSURE_TRUE(scrolledFrame, NS_ERROR_FAILURE); + + nsIFrame* scrollport = nsnull; + scrolledFrame->GetParent(&scrollport); + NS_ASSERTION(scrollport, "No scrollport found"); + NS_ENSURE_TRUE(scrollport, NS_ERROR_FAILURE); - if (view) { - view->GetViewManager(*getter_AddRefs(viewMan)); - if (viewMan) { - if (aGrabMouseEvents) { - viewMan->GrabMouseEvents(view,result); - mIsCapturingMouseEvents = PR_TRUE; - } else { + scrollport->GetView(aPresContext, &view); + } + + NS_ASSERTION(view, "no view???"); + NS_ENSURE_TRUE(view, NS_ERROR_FAILURE); + + nsCOMPtr viewMan; + view->GetViewManager(*getter_AddRefs(viewMan)); + if (viewMan) { + PRBool result; + // It's not clear why we don't have the widget capture mouse events here. + if (aGrabMouseEvents) { + viewMan->GrabMouseEvents(view,result); + mIsCapturingMouseEvents = PR_TRUE; + } else { + nsIView* curGrabber; + viewMan->GetMouseEventGrabber(curGrabber); + if (curGrabber == view) { + // only unset the grabber if *we* are the ones doing the grabbing + // it could be a scrollbar inside this listbox which is actually grabbing + // This shouldn't be necessary. We should simply ensure that events targeting + // scrollbars are never visible to DOM consumers. viewMan->GrabMouseEvents(nsnull,result); - mIsCapturingMouseEvents = PR_FALSE; } - // XXX this is temp code -#if 0 - if (!mIsScrollbarVisible) { - nsIWidget * widget; - view->GetWidget(widget); - if (nsnull != widget) { - widget->CaptureMouse(aGrabMouseEvents); - NS_RELEASE(widget); - } - } -#endif + mIsCapturingMouseEvents = PR_FALSE; } } @@ -1682,7 +1782,7 @@ nsListControlFrame::HandleEvent(nsIPresContext* aPresContext, if (nsFormControlHelper::GetDisabled(mContent)) return NS_OK; - return nsScrollFrame::HandleEvent(aPresContext, aEvent, aEventStatus); + return nsGfxScrollFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } @@ -1701,7 +1801,7 @@ nsListControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mHasBeenInitialized = PR_FALSE; } } - nsresult rv = nsScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); + nsresult rv = nsGfxScrollFrame::SetInitialChildList(aPresContext, aListName, aChildList); // If all the content is here now check // to see if all the frames have been created @@ -1741,8 +1841,8 @@ nsListControlFrame::Init(nsIPresContext* aPresContext, { mPresContext = aPresContext; NS_ADDREF(mPresContext); - nsresult result = nsScrollFrame::Init(aPresContext, aContent, aParent, aContext, - aPrevInFlow); + nsresult result = nsGfxScrollFrame::Init(aPresContext, aContent, aParent, aContext, + aPrevInFlow); // get the receiver interface from the browser button's content node nsCOMPtr receiver(do_QueryInterface(mContent)); @@ -2387,7 +2487,7 @@ NS_IMETHODIMP nsListControlFrame::GetOptionsContainer(nsIPresContext* aPresContext, nsIFrame** aFrame) { - return FirstChild(aPresContext, nsnull, aFrame); + return GetScrolledFrame(aPresContext, *aFrame); } // Send out an onchange notification. @@ -2488,34 +2588,6 @@ nsListControlFrame::GetProperty(nsIAtom* aName, nsAString& aValue) return NS_OK; } - -//--------------------------------------------------------- -// Create a Borderless top level widget for drop-down lists. -nsresult -nsListControlFrame::CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay) -{ - if (IsInDropDownMode() == PR_TRUE) { - nsCOMPtr vm; - aView->GetViewManager(*getter_AddRefs(vm)); - vm->SetViewFloating(aView, PR_TRUE); - - nsWidgetInitData widgetData; - widgetData.mWindowType = eWindowType_popup; - widgetData.mBorderStyle = eBorderStyle_default; - -#if defined(XP_MAC) || defined(XP_MACOSX) - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - aView->CreateWidget(kCPopUpCID, &widgetData, nsnull); -#else - static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); - aView->CreateWidget(kCChildCID, &widgetData, nsnull); -#endif - return NS_OK; - } else { - return nsScrollFrame::CreateScrollingViewWidget(aView, aDisplay); - } -} - //--------------------------------------------------------- void nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, @@ -2552,56 +2624,7 @@ nsListControlFrame::SyncViewWithFrame(nsIPresContext* aPresContext) // as if it were in it's normal position in the view hierarchy. mComboboxFrame->AbsolutelyPositionDropDown(); - nsPoint parentPos; - nsCOMPtr viewManager; - - //Get parent frame - nsIFrame* parent; - GetParentWithView(aPresContext, &parent); - NS_ASSERTION(parent, "GetParentWithView failed"); - - // Get parent view - nsIView* parentView = nsnull; - parent->GetView(aPresContext, &parentView); - - parentView->GetViewManager(*getter_AddRefs(viewManager)); - GetViewOffset(viewManager, parentView, parentPos); - nsIView* view = nsnull; - GetView(aPresContext, &view); - - nsIView* containingView = nsnull; - nsPoint offset; - GetOffsetFromView(aPresContext, offset, &containingView); - //nsSize size; - //GetSize(size); - - //nscoord width; - //nscoord height; - //view->GetDimensions(&width, &height); - - //if (width != mRect.width || height != mRect.height) { - //viewManager->ResizeView(view, mRect.width, mRect.height); - //} - nscoord x; - nscoord y; - view->GetPosition(&x, &y); - - nscoord newX = parentPos.x + offset.x; - nscoord newY = parentPos.y + offset.y; - - //if (newX != x || newY != y) { - viewManager->MoveViewTo(view, newX, newY); - //} - - nsViewVisibility visibility; - - view->GetVisibility(visibility); - const nsStyleVisibility* vis; - GetStyleData(eStyleStruct_Visibility, (const nsStyleStruct*&) vis); - - if (visibility != vis->mVisible) { - //view->SetVisibility(NS_STYLE_VISIBILITY_VISIBLE == disp->mVisible ?nsViewVisibility_kShow:nsViewVisibility_kHide); - } + nsContainerFrame::PositionFrameView(aPresContext, this); return NS_OK; } @@ -2647,35 +2670,6 @@ nsListControlFrame::AboutToRollup() return NS_OK; } -//--------------------------------------------------------- -nsresult -nsListControlFrame::GetScrollingParentView(nsIPresContext* aPresContext, - nsIFrame* aParent, - nsIView** aParentView) -{ - if (IsInDropDownMode() == PR_TRUE) { - // Use the parent frame to get the view manager - nsIView* parentView = nsnull; - nsresult rv = aParent->GetView(aPresContext, &parentView); - NS_ASSERTION(parentView, "GetView failed"); - nsCOMPtr viewManager; - parentView->GetViewManager(*getter_AddRefs(viewManager)); - NS_ASSERTION(viewManager, "GetViewManager failed"); - - // Ask the view manager for the root view and - // use it as the parent for popup scrolling lists. - // Using the normal view as the parent causes the - // drop-down list to be clipped to a parent view. - // Using the root view as the parent - // prevents this from happening. - viewManager->GetRootView(*aParentView); - NS_ASSERTION(aParentView, "GetRootView failed"); - return rv; - } else { - return nsScrollFrame::GetScrollingParentView(aPresContext, aParent, aParentView); - } -} - //--------------------------------------------------------- NS_IMETHODIMP nsListControlFrame::DidReflow(nsIPresContext* aPresContext, @@ -2686,12 +2680,12 @@ nsListControlFrame::DidReflow(nsIPresContext* aPresContext, { //SyncViewWithFrame(); mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - nsresult rv = nsScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); + nsresult rv = nsGfxScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; SyncViewWithFrame(aPresContext); return rv; } else { - nsresult rv = nsScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); + nsresult rv = nsGfxScrollFrame::DidReflow(aPresContext, aReflowState, aStatus); PRInt32 selectedIndex = mEndSelectionIndex; if (selectedIndex == kNothingSelected) { GetSelectedIndex(&selectedIndex); @@ -2710,12 +2704,12 @@ NS_IMETHODIMP nsListControlFrame::MoveTo(nsIPresContext* aPresContext, nscoord a { //SyncViewWithFrame(); mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; - nsresult rv = nsScrollFrame::MoveTo(aPresContext, aX, aY); + nsresult rv = nsGfxScrollFrame::MoveTo(aPresContext, aX, aY); mState |= NS_FRAME_SYNC_FRAME_AND_VIEW; //SyncViewWithFrame(); return rv; } else { - return nsScrollFrame::MoveTo(aPresContext, aX, aY); + return nsGfxScrollFrame::MoveTo(aPresContext, aX, aY); } } @@ -2980,17 +2974,6 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, return rv; } -void -nsListControlFrame::GetScrollableView(nsIScrollableView*& aScrollableView) -{ - aScrollableView = nsnull; - - nsIView * scrollView = nsnull; - GetView(mPresContext, &scrollView); - CallQueryInterface(scrollView, &aScrollableView); - NS_ASSERTION(aScrollableView, "We must be able to get a ScrollableView"); -} - //---------------------------------------------------------------------- nsresult nsListControlFrame::MouseDown(nsIDOMEvent* aMouseEvent) @@ -3081,6 +3064,12 @@ nsListControlFrame::MouseMove(nsIDOMEvent* aMouseEvent) if (NS_SUCCEEDED(GetIndexFromDOMEvent(aMouseEvent, selectedIndex))) { PerformSelection(selectedIndex, PR_FALSE, PR_FALSE); } + + // Make sure the SelectArea frame gets painted + // XXX this shouldn't be needed, but other places in this code do it + // and if we don't do this, invalidation doesn't happen when we move out + // of the top-level window. We should track this down and fix it --- roc + Invalidate(mPresContext, nsRect(0,0,mRect.width,mRect.height), PR_TRUE); } } else {// XXX - temporary until we get drag events if (mButtonDown) { @@ -3149,7 +3138,7 @@ nsresult nsListControlFrame::ScrollToFrame(nsIContent* aOptElement) { nsIScrollableView * scrollableView; - GetScrollableView(scrollableView); + GetScrollableView(mPresContext, &scrollableView); if (scrollableView) { // if null is passed in we scroll to 0,0 diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h index 589a9facfdf..e82ed5a9862 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.h +++ b/mozilla/layout/html/forms/src/nsListControlFrame.h @@ -48,10 +48,11 @@ //#define DO_PIXELS #endif -#include "nsScrollFrame.h" +#include "nsGfxScrollFrame.h" #include "nsIFormControlFrame.h" #include "nsIListControlFrame.h" #include "nsISelectControlFrame.h" +#include "nsIStatefulFrame.h" #include "nsIDOMMouseListener.h" #include "nsIDOMMouseMotionListener.h" #include "nsIDOMKeyListener.h" @@ -169,9 +170,10 @@ protected: * Frame-based listbox. */ -class nsListControlFrame : public nsScrollFrame, +class nsListControlFrame : public nsGfxScrollFrame, public nsIFormControlFrame, public nsIListControlFrame, + public nsIStatefulFrame, public nsIDOMMouseListener, public nsIDOMMouseMotionListener, public nsIDOMKeyListener, @@ -223,8 +225,6 @@ public: */ NS_IMETHOD GetFrameType(nsIAtom** aType) const; - virtual PRBool SupportsVisibilityHidden() { return PR_FALSE; } - #ifdef DEBUG // nsIFrameDebug NS_IMETHOD GetFrameName(nsAString& aResult) const; @@ -290,6 +290,10 @@ public: NS_IMETHOD GetDummyFrame(nsIFrame** aFrame); NS_IMETHOD SetDummyFrame(nsIFrame* aFrame); + //nsIStatefulFrame + NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); + NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + //nsIDOMEventListener NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent); NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent); @@ -339,16 +343,9 @@ protected: PRInt32 aNumOptions, PRInt32 aDoAdjustInc, PRInt32 aDoAdjustIncNext); virtual void ResetList(nsIPresContext* aPresContext, nsVoidArray * aInxList = nsnull); - nsListControlFrame(); + nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument); virtual ~nsListControlFrame(); - // nsScrollFrame overrides - // Override the widget created for the list box so a Borderless top level - // widget is created for drop-down lists. - virtual nsresult CreateScrollingViewWidget(nsIView* aView, const nsStyleDisplay* aDisplay); - virtual nsresult GetScrollingParentView(nsIPresContext* aPresContext, - nsIFrame* aParent, - nsIView** aParentView); // Utility methods nsresult GetSizeAttribute(PRInt32 *aSize); nsIContent* GetOptionFromContent(nsIContent *aContent); @@ -361,7 +358,6 @@ protected: PRBool CheckIfAllFramesHere(); PRInt32 GetIndexFromContent(nsIContent *aContent); PRBool IsLeftButton(nsIDOMEvent* aMouseEvent); - void GetScrollableView(nsIScrollableView*& aScrollableView); // Dropped down stuff void SetComboboxItem(PRInt32 aIndex); diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp index 24e9040184a..45dd3d2e4f7 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp @@ -3158,7 +3158,8 @@ nsTextControlFrame::GetWidthInCharacters() const } NS_IMETHODIMP -nsTextControlFrame::GetScrollableView(nsIScrollableView** aView) +nsTextControlFrame::GetScrollableView(nsIPresContext* aPresContext, + nsIScrollableView** aView) { nsresult rv = NS_OK; *aView = mScrollableView; diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.h b/mozilla/layout/html/forms/src/nsTextControlFrame.h index 88a88a61a95..21fc91427fb 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.h +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.h @@ -287,7 +287,7 @@ protected: PRInt32 GetWidthInCharacters() const; // nsIScrollableViewProvider - NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + NS_IMETHOD GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView); private: //helper methods diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 5f79293a80b..16030e35552 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -187,6 +187,7 @@ NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aN #include "nsIScrollable.h" #include "nsINodeInfo.h" #include "prenv.h" +#include "nsWidgetsCID.h" // Global object maintenance nsIXBLService * nsCSSFrameConstructor::gXBLService = nsnull; @@ -2573,7 +2574,7 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewInnerFrame, - childItems); + PR_FALSE, childItems); // Set the inner table frame's initial primary list aNewInnerFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -2695,7 +2696,7 @@ nsCSSFrameConstructor::ConstructTableRowGroupFrame(nsIPresShell* aPre if (NS_FAILED(rv)) return rv; // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (aIsPseudoParent) { @@ -2806,7 +2807,7 @@ nsCSSFrameConstructor::ConstructTableRowFrame(nsIPresShell* aPresShel if (NS_FAILED(rv)) return rv; // if there are any anonymous children for the table, create frames for them CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); if (aIsPseudoParent) { @@ -3546,7 +3547,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, // This must happen before ProcessChildren to ensure that popups are // never constructed before the popupset. CreateAnonymousFrames(aPresShell, aPresContext, nsnull, aState, aDocElement, contentFrame, - childItems, PR_TRUE); + PR_FALSE, childItems, PR_TRUE); ProcessChildren(aPresShell, aPresContext, aState, aDocElement, contentFrame, PR_TRUE, childItems, isBlockFrame); @@ -3874,6 +3875,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIFrame* newScrollableFrame = nsnull; + newFrame = nsnull; rootPseudoStyle = BeginBuildingScrollFrame( aPresShell, aPresContext, state, @@ -4357,6 +4359,11 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, nsIFrame* scrolledFrame = nsnull; NS_NewSelectsAreaFrame(aPresShell, &scrolledFrame, flags); + // make sure any existing anonymous content is cleared out. Gfx scroll frame construction + // should reset it to just be the anonymous scrollbars, but we don't want to depend + // on that. + aPresShell->SetAnonymousContentFor(aContent, nsnull); + InitializeSelectFrame(aPresShell, aPresContext, aState, listFrame, scrolledFrame, aContent, comboboxFrame, listStyle, PR_FALSE, PR_FALSE, PR_TRUE); newFrame = listFrame; @@ -4381,10 +4388,12 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, NS_RELEASE(viewWidget); //listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); - // Create display and button frames from the combobox's anonymous content + // Create display and button frames from the combobox's anonymous content. + // The anonymous content is appended to existing anonymous content for this + // element (the scrollbars). nsFrameItems childItems; CreateAnonymousFrames(aPresShell, aPresContext, nsHTMLAtoms::combobox, - aState, aContent, comboboxFrame, childItems); + aState, aContent, comboboxFrame, PR_TRUE, childItems); comboboxFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -4429,14 +4438,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, aNewFrame = listFrame; - // Set flag so the events go to the listFrame not child frames. - // XXX: We should replace this with a real widget manager similar - // to how the nsFormControlFrame works. - // Re-directing events is a temporary Kludge. - nsIView *listView; - listFrame->GetView(aPresContext, &listView); - NS_ASSERTION(nsnull != listView,"ListFrame's view is nsnull"); - //listView->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN); aFrameHasBeenInitialized = PR_TRUE; } } @@ -4460,7 +4461,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, nsStyleContext* aStyleContext, PRBool aIsAbsolutelyPositioned, PRBool aIsFixedPositioned, - PRBool aCreateBlock) + PRBool aBuildCombobox) { // Initialize it nsIFrame* geometricParent = aParentFrame; @@ -4471,24 +4472,48 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, geometricParent = aState.mFixedItems.containingBlock; } - nsRefPtr scrolledPseudoStyle; + // We don't call InitAndRestoreFrame for scrollFrame because we can only + // restore the frame state after its parts have been created (in particular, + // the scrollable view). So we have to split Init and Restore. - - scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsCSSAnonBoxes::scrolledContent, - aStyleContext); + // Initialize the frame + scrollFrame->Init(aPresContext, aContent, geometricParent, aStyleContext, nsnull); - InitAndRestoreFrame(aPresContext, aState, aContent, - geometricParent, aStyleContext, nsnull, scrollFrame); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, scrollFrame, + aStyleContext, aParentFrame, aBuildCombobox); + if (aBuildCombobox) { + // Give the drop-down list a popup widget + nsIView * view; + scrollFrame->GetView(aPresContext, &view); + NS_ASSERTION(view, "We asked for a view but didn't get one"); + if (view) { + nsCOMPtr vm; + view->GetViewManager(*getter_AddRefs(vm)); + vm->SetViewFloating(view, PR_TRUE); - // Initialize the frame and force it to have a view - // the scrolled frame is anonymous and does not have a content node - InitAndRestoreFrame(aPresContext, aState, aContent, - scrollFrame, scrolledPseudoStyle, nsnull, scrolledFrame); + nsWidgetInitData widgetData; + widgetData.mWindowType = eWindowType_popup; + widgetData.mBorderStyle = eBorderStyle_default; - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, scrolledFrame, - scrolledPseudoStyle, nsnull, PR_TRUE); +#if defined(XP_MAC) || defined(XP_MACOSX) + static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); + view->CreateWidget(kCPopUpCID, &widgetData, nsnull); +#else + static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); + view->CreateWidget(kCChildCID, &widgetData, nsnull); +#endif + } + } + nsStyleContext* scrolledPseudoStyle; + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, aStyleContext, + scrolledFrame, geometricParent, aParentFrame, scrollFrame, + scrolledPseudoStyle); + + if (aState.mFrameState && aState.mFrameManager) { + // Restore frame state for the scroll frame + aState.mFrameManager->RestoreFrameStateFor(aPresContext, scrollFrame, aState.mFrameState); + } // The area frame is a floater container PRBool haveFirstLetterStyle, haveFirstLineStyle; @@ -4541,17 +4566,9 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsIPresShell* aPresShell, aState.mFloatedItems.childList); } - // Set the scroll frame's initial child list - scrollFrame->SetInitialChildList(aPresContext, nsnull, scrolledFrame); - return NS_OK; } -/** - * Used to be InitializeScrollFrame but now its only used for the select tag - * But the select tag should really be fixed to use GFX scrollbars that can - * be create with BuildScrollFrame. - */ nsresult nsCSSFrameConstructor::ConstructFieldSetFrame(nsIPresShell* aPresShell, nsIPresContext* aPresContext, @@ -5071,7 +5088,7 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell, // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list @@ -5229,6 +5246,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell nsFrameConstructorState& aState, nsIContent* aParent, nsIFrame* aNewFrame, + PRBool aAppendToExisting, nsFrameItems& aChildItems, PRBool aIsRoot) { @@ -5252,7 +5270,8 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell ) return NS_OK; - return CreateAnonymousFrames(aPresShell, aPresContext, aState, aParent, mDocument, aNewFrame, aChildItems); + return CreateAnonymousFrames(aPresShell, aPresContext, aState, aParent, + mDocument, aNewFrame, aAppendToExisting, aChildItems); } // after the node has been constructed and initialized create any @@ -5264,6 +5283,7 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell nsIContent* aParent, nsIDocument* aDocument, nsIFrame* aParentFrame, + PRBool aAppendToExisting, nsFrameItems& aChildItems) { nsCOMPtr creator(do_QueryInterface(aParentFrame)); @@ -5279,6 +5299,29 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell anonymousItems->Count(&count); if (count) { + // A content element can have multiple sources of anonymous content. For example, + // SELECTs have a combobox dropdown button and also scrollbars in the list view. + // nsPresShell doesn't handle this very well. It's a problem because a reframe could + // cause anonymous content from one source to be destroyed and recreated while + // (in theory) leaving the rest intact, but the presshell doesn't have a way of tracking + // the anonymous content at that granularity. + + // So what we're doing right now is wiping out existing content whenever we get new + // anonymous content, except for the one case we care about where there are multiple + // sources (SELECTs). This case is handled by having SELECT initialization tell us + // explicitly not to wipe out the scrollbars when the combobox anonymous content is + // added. + // Note that we only wipe out existing content when there is actual new content. + // Otherwise we wipe out scrollbars and other anonymous content when we check sources + // that never provide anonymous content (e.g. the call to CreateAnonymousFrames + // from ConstructBlock). + + // What we SHOULD do is get rid of the presshell's need to track anonymous + // content. It's only used for cleanup as far as I can tell. + if (!aAppendToExisting) { + aPresShell->SetAnonymousContentFor(aParent, nsnull); + } + // Inform the pres shell about the anonymous content aPresShell->SetAnonymousContentFor(aParent, anonymousItems); @@ -5912,7 +5955,7 @@ nsCSSFrameConstructor::ConstructXULFrame(nsIPresShell* aPresShell, } CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, - newFrame, childItems); + newFrame, PR_FALSE, childItems); // Set the frame's initial child list newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6028,7 +6071,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresSh nsIFrame* scrollFrame = nsnull; nsIFrame* parentFrame = nsnull; - nsIFrame* gfxScrollFrame = nsnull; + nsIFrame* gfxScrollFrame = aNewFrame; nsFrameItems anonymousItems; @@ -6037,9 +6080,20 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsIPresShell* aPresSh PRBool isGfx = HasGfxScrollbars(); if (isGfx) { - BuildGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, - aParentFrame, aContentParentFrame, contentStyle, - aIsRoot, gfxScrollFrame, anonymousItems, aScrollPortFrame); + if (!gfxScrollFrame) { + NS_NewGfxScrollFrame(aPresShell, &gfxScrollFrame, aDocument, aIsRoot); + + InitAndRestoreFrame(aPresContext, aState, aContent, + aParentFrame, contentStyle, nsnull, gfxScrollFrame); + + // Create a view + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, gfxScrollFrame, + contentStyle, aContentParentFrame, PR_FALSE); + } + + InitGfxScrollFrame(aPresShell, aPresContext, aState, aContent, aDocument, + aParentFrame, aContentParentFrame, contentStyle, + aIsRoot, gfxScrollFrame, anonymousItems, aScrollPortFrame); scrollFrame = anonymousItems.childList; // get the scrollport from the anonymous list parentFrame = gfxScrollFrame; @@ -6182,6 +6236,7 @@ nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIPresContext* aPresConte * * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the * scrolled frame you passed in. (returned) + * If this is not null, we'll just use it * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned) */ nsresult @@ -6256,32 +6311,24 @@ nsCSSFrameConstructor::BuildScrollFrame(nsIPresShell* aPresShell, /** * 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::BuildGfxScrollFrame (nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aContent, - nsIDocument* aDocument, - nsIFrame* aParentFrame, - nsIFrame* aContentParentFrame, - nsStyleContext* aStyleContext, - PRBool aIsRoot, - nsIFrame*& aNewFrame, - nsFrameItems& aAnonymousFrames, - nsIFrame* aScrollPortFrame) +nsCSSFrameConstructor::InitGfxScrollFrame(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames, + nsIFrame* aScrollPortFrame) { #ifdef INCLUDE_XUL - NS_NewGfxScrollFrame(aPresShell, &aNewFrame, aDocument, aIsRoot); - - InitAndRestoreFrame(aPresContext, aState, aContent, - aParentFrame, aStyleContext, nsnull, aNewFrame); - - // Create a view - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, - aStyleContext, aContentParentFrame, PR_FALSE); - - if (!aScrollPortFrame) NS_NewScrollPortFrame(aPresShell, &aScrollPortFrame); @@ -6289,7 +6336,7 @@ nsCSSFrameConstructor::BuildGfxScrollFrame (nsIPresShell* aPresShell, // if there are any anonymous children for the nsScrollFrame create frames for them. CreateAnonymousFrames(aPresShell, aPresContext, aState, aContent, aDocument, aNewFrame, - aAnonymousFrames); + PR_FALSE, aAnonymousFrames); return NS_OK; #endif @@ -6420,7 +6467,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the scrolled frame's initial child lists scrolledFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6485,7 +6532,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list(s) newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -6537,7 +6584,7 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresShell* aPre nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list(s) newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -7063,7 +7110,7 @@ nsCSSFrameConstructor::ConstructMathMLFrame(nsIPresShell* aPresShell, childItems, PR_FALSE); CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); } // Set the frame's initial child list @@ -7207,7 +7254,7 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsIPresShell* aPresShell, newFrame, PR_TRUE, childItems, isBlock); CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - childItems); + PR_FALSE, childItems); } // Set the frame's initial child list @@ -8429,7 +8476,7 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext, nsIContent* item = nsCOMPtr(*iter); if (item == child) // Call ContentInserted with this index. - ContentInserted(aPresContext, aContainer, child, iter.index(), mTempFrameTreeState, PR_FALSE); + ContentInserted(aPresContext, aContainer, nsnull, child, iter.index(), mTempFrameTreeState, PR_FALSE); } } @@ -8932,6 +8979,7 @@ nsCSSFrameConstructor::NeedSpecialFrameReframe(nsIPresShell* aPresShell, NS_IMETHODIMP nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, nsIContent* aContainer, + nsIFrame* aContainerFrame, nsIContent* aChild, PRInt32 aIndexInContainer, nsILayoutHistoryState* aFrameState, @@ -8939,7 +8987,6 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, { // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and // the :empty pseudo-class? - #ifdef DEBUG if (gNoisyContentUpdates) { printf("nsCSSFrameConstructor::ContentInserted container=%p child=%p index=%d\n", @@ -9060,10 +9107,13 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, } // Otherwise, we've got parent content. Find its frame. - nsIFrame* parentFrame = GetFrameFor(shell, aPresContext, aContainer); - if (! parentFrame) - return NS_OK; // XXXwaterson will this break selects? (See ``Here - // we have been notified...'' below.) + nsIFrame* parentFrame = aContainerFrame; + if (!parentFrame) { + parentFrame = GetFrameFor(shell, aPresContext, aContainer); + if (! parentFrame) + return NS_OK; // XXXwaterson will this break selects? (See ``Here + // we have been notified...'' below.) + } // See if we have an XBL insertion point. If so, then that's our // real parent frame; if not, then the frame hasn't been built yet @@ -9385,7 +9435,7 @@ nsCSSFrameConstructor::ContentReplaced(nsIPresContext* aPresContext, aOldChild, aIndexInContainer, PR_TRUE); if (NS_SUCCEEDED(res)) { - res = ContentInserted(aPresContext, aContainer, + res = ContentInserted(aPresContext, aContainer, nsnull, aNewChild, aIndexInContainer, nsnull, PR_TRUE); } @@ -9678,10 +9728,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, // For "select" add the pseudo frame after the last item is deleted nsIFrame* parentFrame = nsnull; childFrame->GetParent(&parentFrame); - if (parentFrame == selectFrame) { - return NS_ERROR_FAILURE; - } - if (shell && parentFrame) { + if (shell && parentFrame && parentFrame != selectFrame) { nsFrameConstructorState state(aPresContext, nsnull, nsnull, nsnull); AddDummyFrameToSelect(aPresContext, shell, state, @@ -12108,20 +12155,25 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, nsCOMPtr container; aContent->GetParent(*getter_AddRefs(container)); if (container) { - PRInt32 indexInContainer; + PRInt32 indexInContainer; rv = container->IndexOf(aContent, indexInContainer); if (NS_SUCCEEDED(rv)) { // Before removing the frames associated with the content object, ask them to save their // state onto a temporary state object. CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); + // Save parent frame because this frame is going away + nsIFrame* parent = nsnull; + if (frame) + frame->GetParent(&parent); + // Remove the frames associated with the content object on which the // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); if (NS_SUCCEEDED(rv)) { // Now, recreate the frames associated with this content object. - rv = ContentInserted(aPresContext, container, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); + rv = ContentInserted(aPresContext, container, parent, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); } } } else { @@ -13374,7 +13426,7 @@ nsCSSFrameConstructor::ConstructBlock(nsIPresShell* aPresShell, nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); // Set the frame's initial child list aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); @@ -13515,7 +13567,7 @@ nsCSSFrameConstructor::ConstructInline(nsIPresShell* aPresShell, nsCOMPtr tag; aContent->GetTag(*getter_AddRefs(tag)); CreateAnonymousFrames(aPresShell, aPresContext, tag, aState, aContent, aNewFrame, - childItems); + PR_FALSE, childItems); aNewFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h index 47780b79b0c..11474eca27e 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h @@ -107,6 +107,7 @@ public: NS_IMETHOD ContentInserted(nsIPresContext* aPresContext, nsIContent* aContainer, + nsIFrame* aContainerFrame, nsIContent* aChild, PRInt32 aIndexInContainer, nsILayoutHistoryState* aFrameState, @@ -574,22 +575,24 @@ protected: nsFrameItems& aFrameItems, PRBool aXBLBaseTag); - nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsIAtom* aTag, - nsFrameConstructorState& aState, - nsIContent* aParent, - nsIFrame* aNewFrame, - nsFrameItems& aChildItems, - PRBool aIsRoot = PR_FALSE); + nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsIAtom* aTag, + nsFrameConstructorState& aState, + nsIContent* aParent, + nsIFrame* aNewFrame, + PRBool aAppendToExisting, + nsFrameItems& aChildItems, + PRBool aIsRoot = PR_FALSE); - nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aParent, - nsIDocument* aDocument, - nsIFrame* aNewFrame, - nsFrameItems& aChildItems); + nsresult CreateAnonymousFrames(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aParent, + nsIDocument* aDocument, + nsIFrame* aNewFrame, + PRBool aAppendToExisting, + nsFrameItems& aChildItems); //MathML Mod - RBS #ifdef MOZ_MATHML @@ -737,18 +740,18 @@ protected: // Creates a new GfxScrollFrame, Initializes it, and creates a scroll port for it // nsresult - BuildGfxScrollFrame(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsFrameConstructorState& aState, - nsIContent* aContent, - nsIDocument* aDocument, - nsIFrame* aParentFrame, - nsIFrame* aContentParentFrame, - nsStyleContext* aStyleContext, - PRBool aIsRoot, - nsIFrame*& aNewFrame, - nsFrameItems& aAnonymousFrames, - nsIFrame* aScrollPort = nsnull); + InitGfxScrollFrame(nsIPresShell* aPresShell, + nsIPresContext* aPresContext, + nsFrameConstructorState& aState, + nsIContent* aContent, + nsIDocument* aDocument, + nsIFrame* aParentFrame, + nsIFrame* aContentParentFrame, + nsStyleContext* aStyleContext, + PRBool aIsRoot, + nsIFrame*& aNewFrame, + nsFrameItems& aAnonymousFrames, + nsIFrame* aScrollPort = nsnull); nsresult diff --git a/mozilla/layout/style/forms.css b/mozilla/layout/style/forms.css index 7062def52c7..a6651d749de 100644 --- a/mozilla/layout/style/forms.css +++ b/mozilla/layout/style/forms.css @@ -171,11 +171,8 @@ select > input[type="button"]:active { background-image: url("arrowd.gif") !important; } -select[size], :-moz-select-scrolled-content { - overflow: -moz-scrollbars-vertical; -} - select[size] { + overflow: -moz-scrollbars-vertical; -moz-appearance: listbox; } @@ -239,7 +236,7 @@ optgroup:before { background-color: inherit; -moz-user-select: none; - border: 1px outset black !important; + border: 1px outset black !important; } input[disabled], diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index 5929c85fabf..6852aaed671 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -1707,7 +1707,7 @@ NS_IMETHODIMP StyleSetImpl::ContentInserted(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aIndexInContainer) { - return mFrameConstructor->ContentInserted(aPresContext, aContainer, + return mFrameConstructor->ContentInserted(aPresContext, aContainer, nsnull, aChild, aIndexInContainer, nsnull, PR_FALSE); } diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index ebeb77f22ea..8cbd955660e 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -2135,7 +2135,7 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild) } NS_IMETHODIMP -nsMenuFrame::GetScrollableView(nsIScrollableView** aView) +nsMenuFrame::GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView) { *aView = nsnull; if (!mPopupFrames.FirstChild()) diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index 2d79d8ae11a..e1248b7fc72 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -168,7 +168,7 @@ public: // nsIScrollableViewProvider methods - NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + NS_IMETHOD GetScrollableView(nsIPresContext* aPresContext, nsIScrollableView** aView); // nsMenuFrame methods diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.cpp b/mozilla/layout/xul/base/src/nsSliderFrame.cpp index f66d3790959..2b8bcc023b8 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSliderFrame.cpp @@ -894,6 +894,8 @@ NS_IMETHODIMP nsSliderFrame::GetFrameForPoint(nsIPresContext* aPresContext, if ((aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)) return NS_ERROR_FAILURE; + // This is EVIL, we shouldn't be messing with GetFrameForPoint just to get + // thumb mouse drag events to arrive at the slider! if (isDraggingThumb(aPresContext)) { // XXX I assume it's better not to test for visibility here. diff --git a/mozilla/xpfe/global/resources/content/xul.css b/mozilla/xpfe/global/resources/content/xul.css index d7322384b0e..d2516692c00 100644 --- a/mozilla/xpfe/global/resources/content/xul.css +++ b/mozilla/xpfe/global/resources/content/xul.css @@ -723,6 +723,11 @@ scrollbar { direction: ltr; } +scrollbar[collapsed="true"], +scrollbar[moz-collapsed="true"] { + -moz-binding: none; +} + thumb { -moz-binding: url(chrome://global/content/bindings/scrollbar.xml#thumb);