diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 2e84b8ad105f8..9a8712d534298 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -88,7 +88,6 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap, // ----- nsIScrollPositionListener --------------------------- NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY); - virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {} NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY); // nsIDocumentObserver diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 09bdda45a5e55..8e0ee61f24941 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -990,8 +990,7 @@ nsGenericElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent) // It doesn't really matter what we use as aRelativeTo here, since // we only care about the size. Using 'parent' might make things // a bit faster by speeding up the internal GetOffsetTo operations. - nsIFrame* parent = frame->GetParent() ? frame->GetParent() : frame; - nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent); + nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, nsnull); aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width); aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height); } diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 09b41433e399f..4eca512df6261 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -264,8 +264,7 @@ nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent, // static nsIFrame* -nsLayoutUtils::GetCrossDocParentFrame(const nsIFrame* aFrame, - nsPoint* aExtraOffset) +nsLayoutUtils::GetCrossDocParentFrame(nsIFrame* aFrame) { nsIFrame* p = aFrame->GetParent(); if (p) @@ -277,9 +276,6 @@ nsLayoutUtils::GetCrossDocParentFrame(const nsIFrame* aFrame, v = v->GetParent(); // anonymous inner view if (!v) return nsnull; - if (aExtraOffset) { - *aExtraOffset += v->GetPosition(); - } v = v->GetParent(); // subdocumentframe's view if (!v) return nsnull; diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 0929c02ce5b7b..486d769df4c8b 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -229,11 +229,8 @@ class nsLayoutUtils * Get the parent of aFrame. If aFrame is the root frame for a document, * and the document has a parent document in the same view hierarchy, then * we try to return the subdocumentframe in the parent document. - * @param aExtraOffset [in/out] if non-null, then as we cross documents - * an extra offset may be required and it will be added to aCrossDocOffset */ - static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame, - nsPoint* aCrossDocOffset = nsnull); + static nsIFrame* GetCrossDocParentFrame(nsIFrame* aFrame); /** * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 31bb2be5c146c..aacf89090f84b 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -479,7 +479,7 @@ nsComboboxControlFrame::ReflowDropdown(nsPresContext* aPresContext, // Allow the child to move/size/change-visibility its view if it's currently // dropped down - PRInt32 flags = NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_VISIBILITY | NS_FRAME_NO_SIZE_VIEW; + PRInt32 flags = NS_FRAME_NO_MOVE_VIEW | NS_FRAME_NO_VISIBILITY | NS_FRAME_NO_SIZE_VIEW; if (mDroppedDown) { flags = 0; } diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 4c67414c4e7f1..472f7261cf26e 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -764,7 +764,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, // and its view if requested aKidFrame->WillReflow(aPresContext); - if (NS_FRAME_NO_MOVE_FRAME == (aFlags & NS_FRAME_NO_MOVE_FRAME)) { + if (0 == (aFlags & NS_FRAME_NO_MOVE_FRAME)) { if ((aFlags & NS_FRAME_INVALIDATE_ON_MOVE) && !(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) && aKidFrame->GetPosition() != nsPoint(aX, aY)) { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 440a070eb2c6c..641f049f77aab 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2154,7 +2154,7 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext, PRUint8 selectStyle; IsSelectable(&selectable, &selectStyle); // XXX Do we really need to exclude non-selectable content here? - // GetContentOffsetsFromPoint can handle it just fine, although some + // GetContentAndOffsetsFromPoint can handle it just fine, although some // other stuff might not like it. if (!selectable) return NS_OK; @@ -3452,25 +3452,22 @@ nsPoint nsIFrame::GetOffsetTo(const nsIFrame* aOther) const { NS_PRECONDITION(aOther, "Must have frame for destination coordinate system!"); + // Note that if we hit a view while walking up the frame tree we need to stop + // and switch to traversing the view tree so that we will deal with scroll + // views properly. nsPoint offset(0, 0); const nsIFrame* f; - for (f = this; f != aOther && f; - f = nsLayoutUtils::GetCrossDocParentFrame(f, &offset)) { + for (f = this; !f->HasView() && f != aOther; f = f->GetParent()) { offset += f->GetPosition(); } - + if (f != aOther) { - // Looks like aOther wasn't an ancestor of |this|. So now we have - // the root-document-relative position of |this| in |offset|. Convert back - // to the coordinates of aOther - nsPoint negativeOffset(0,0); - while (aOther) { - offset -= aOther->GetPosition(); - aOther = nsLayoutUtils::GetCrossDocParentFrame(aOther, &negativeOffset); - } - offset -= negativeOffset; + // We found a view. Switch to the view tree + nsPoint toViewOffset(0, 0); + nsIView* otherView = aOther->GetClosestView(&toViewOffset); + offset += f->GetView()->GetOffsetTo(otherView) - toViewOffset; } - + return offset; } @@ -3537,6 +3534,88 @@ NS_IMETHODIMP nsFrame::GetOffsetFromView(nsPoint& aOffset, return NS_OK; } +// The (x,y) value of the frame's upper left corner is always +// relative to its parentFrame's upper left corner, unless +// its parentFrame has a view associated with it, in which case, it +// will be relative to the upper left corner of the view returned +// by a call to parentFrame->GetView(). +// +// This means that while drilling down the frame hierarchy, from +// parent to child frame, we sometimes need to take into account +// crossing these view boundaries, because the coordinate system +// changes from parent frame coordinate system, to the associated +// view's coordinate system. +// +// GetOriginToViewOffset() is a utility method that returns the +// offset necessary to map a point, relative to the frame's upper +// left corner, into the coordinate system of the view associated +// with the frame. +// +// If there is no view associated with the frame, or the view is +// not a descendant of the frame's parent view (ex: scrolling popup menu), +// the offset returned will be (0,0). + +NS_IMETHODIMP nsFrame::GetOriginToViewOffset(nsPoint& aOffset, + nsIView** aView) const +{ + nsresult rv = NS_OK; + + aOffset.MoveTo(0,0); + + if (aView) + *aView = nsnull; + + if (HasView()) { + nsIView *view = GetView(); + nsIView *parentView = nsnull; + nsPoint offsetToParentView; + rv = GetOffsetFromView(offsetToParentView, &parentView); + + if (NS_SUCCEEDED(rv)) { + nsPoint viewOffsetFromParent(0,0); + nsIView *pview = view; + + nsIViewManager* vVM = view->GetViewManager(); + + while (pview && pview != parentView) { + viewOffsetFromParent += pview->GetPosition(); + + nsIView *tmpView = pview->GetParent(); + if (tmpView && vVM != tmpView->GetViewManager()) { + // Don't cross ViewManager boundaries! + // XXXbz why not? + break; + } + pview = tmpView; + } + +#ifdef DEBUG_KIN + if (pview != parentView) { + // XXX: At this point, pview is probably null since it traversed + // all the way up view's parent hierarchy and did not run across + // parentView. In the future, instead of just returning an offset + // of (0,0) for this case, we may want offsetToParentView to + // include the offset from the parentView to the top of the + // view hierarchy which would make both offsetToParentView and + // viewOffsetFromParent, offsets to the global coordinate space. + // We'd have to investigate any perf impact this would have before + // checking in such a change, so for now we just return (0,0). + // -- kin + NS_WARNING("view is not a descendant of parentView!"); + } +#endif // DEBUG + + if (pview == parentView) + aOffset = offsetToParentView - viewOffsetFromParent; + + if (aView) + *aView = view; + } + } + + return rv; +} + /* virtual */ PRBool nsIFrame::AreAncestorViewsVisible() const { diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 5dc5d5b9f81f8..e93195373538d 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -228,6 +228,7 @@ class nsFrame : public nsBox virtual nsIFrame* GetNextInFlowVirtual() const; NS_IMETHOD SetNextInFlow(nsIFrame*); NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const; + NS_IMETHOD GetOriginToViewOffset(nsPoint& aOffset, nsIView **aView) const; virtual nsIAtom* GetType() const; virtual PRBool IsContainingBlock() const; #ifdef NS_DEBUG diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index bfc58891641d1..4261737f97a24 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1793,14 +1793,6 @@ nsGfxScrollFrameInner::InternalScrollPositionDidChange(nscoord aX, nscoord aY) aX - GetScrolledRect(GetScrollPortSize()).x); } -void -nsGfxScrollFrameInner::ViewPositionDidChange(nsIScrollableView* aScrollable) -{ - // Update frame position to match view offsets - nsPoint childOffset = mScrolledFrame->GetView()->GetOffsetTo(mOuter->GetView()); - mScrolledFrame->SetPosition(childOffset); -} - /** * Called whenever actual scrolling happens for any reason. */ @@ -1809,6 +1801,10 @@ nsGfxScrollFrameInner::ScrollPositionDidChange(nsIScrollableView* aScrollable, n { NS_ASSERTION(!mViewInitiatedScroll, "Cannot reenter ScrollPositionDidChange"); + // Update frame position to match view offsets + nsPoint childOffset = mScrolledFrame->GetView()->GetOffsetTo(mOuter->GetView()); + mScrolledFrame->SetPosition(childOffset); + mViewInitiatedScroll = PR_TRUE; InternalScrollPositionDidChange(aX, aY); mViewInitiatedScroll = PR_FALSE; diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index bbd9d3e00354d..0f02a0f0fef24 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -99,7 +99,6 @@ class nsGfxScrollFrameInner : public nsIScrollPositionListener, // nsIScrollPositionListener NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); - virtual void ViewPositionDidChange(nsIScrollableView* aScrollable); NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); // This gets called when the 'curpos' attribute on one of the scrollbars changes diff --git a/layout/generic/nsHTMLFrame.cpp b/layout/generic/nsHTMLFrame.cpp index 82f6624561a2a..ebe3a82b34a5c 100644 --- a/layout/generic/nsHTMLFrame.cpp +++ b/layout/generic/nsHTMLFrame.cpp @@ -115,8 +115,7 @@ class CanvasFrame : public nsHTMLContainerFrame, // nsIScrollPositionListener NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); - virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {} - NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); + NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); // nsICanvasFrame NS_IMETHOD SetHasFocus(PRBool aHasFocus); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 2f302b8ad0816..1cf87588670cf 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -104,10 +104,10 @@ struct nsMargin; typedef class nsIFrame nsIBox; // IID for the nsIFrame interface -// 98a0c040-09cf-408b-b55f-321b4f8d9d67 -#define NS_IFRAME_IID \ - { 0x98a0c040, 0x09cf, 0x408b, \ - { 0xb5, 0x5f, 0x32, 0x1b, 0x4f, 0x8d, 0x9d, 0x67 } } +// 04a7dee5-3435-47dc-bd42-a36c0f66a42c + #define NS_IFRAME_IID \ +{ 0x04a7dee5, 0x3435, 0x47dc, \ + { 0xbd, 0x42, 0xa3, 0x6c, 0x0f, 0x66, 0xa4, 0x2c } } /** * Indication of how the frame can be split. This is used when doing runaround @@ -1529,6 +1529,17 @@ class nsIFrame : public nsISupports NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const = 0; + /** + * Returns the offset from this frame's upper left corner to the upper + * left corner of the view returned by a call to GetView(). aOffset + * will contain the offset to the view or (0,0) if the frame has no + * view. aView will contain a pointer to the view returned by GetView(). + * aView is optional, that is, you may pass null if you are not interested + * in getting a pointer to the view. + */ + NS_IMETHOD GetOriginToViewOffset(nsPoint& aOffset, + nsIView** aView) const = 0; + /** * Returns true if and only if all views, from |GetClosestView| up to * the top of the view hierarchy are visible. diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index e761fa47dc1b9..7fe0b5f41acd8 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -386,7 +386,6 @@ class nsPluginInstanceOwner : public nsIPluginInstanceOwner, // nsIScrollPositionListener interface NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); - virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {} NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); //locals diff --git a/layout/xul/base/src/nsBox.cpp b/layout/xul/base/src/nsBox.cpp index 762c59c9b93d5..fcf770ee68af1 100644 --- a/layout/xul/base/src/nsBox.cpp +++ b/layout/xul/base/src/nsBox.cpp @@ -274,7 +274,7 @@ nsBox::SetBounds(nsBoxLayoutState& aState, const nsRect& aRect, PRBool aRemoveOv flags |= stateFlags; - if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME) + if (flags & NS_FRAME_NO_MOVE_FRAME) SetSize(nsSize(aRect.width, aRect.height)); else SetRect(aRect); diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index eafb10be1f0cd..94459a22d01e7 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -885,9 +885,6 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame) nsPresContext* presContext = PresContext(); nsIFrame* rootFrame = presContext->PresShell()->FrameManager()->GetRootFrame(); - NS_ASSERTION(rootFrame->GetView() && GetView() && - rootFrame->GetView() == GetView()->GetParent(), - "rootFrame's view is not our view's parent???"); // if the frame is not specified, use the anchor node passed to ShowPopup. If // that wasn't specified either, use the root frame. Note that mAnchorContent @@ -1240,9 +1237,11 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame) presContext->GetViewManager()->MoveViewTo(GetView(), xpos, ypos); // Now that we've positioned the view, sync up the frame's origin. - // Note that (xpos,ypos) is the position relative to rootFrame. - nsBoxFrame::SetPosition(nsPoint(xpos, ypos) - - GetParent()->GetOffsetTo(rootFrame)); + nsPoint frameOrigin = GetPosition(); + nsPoint offsetToView; + GetOriginToViewOffset(offsetToView, nsnull); + frameOrigin -= offsetToView; + nsBoxFrame::SetPosition(frameOrigin); if (sizedToPopup) { nsBoxLayoutState state(PresContext()); diff --git a/view/public/nsIScrollPositionListener.h b/view/public/nsIScrollPositionListener.h index 4370c5a1b259b..62928645bbefd 100644 --- a/view/public/nsIScrollPositionListener.h +++ b/view/public/nsIScrollPositionListener.h @@ -47,11 +47,9 @@ class nsIScrollableView; // IID for the nsIScrollPositionListener interface -// {98a0c040-09cf-408b-b55f-321b4f8d9d67} - +// {f8dfc500-6ad1-11d3-8360-a3f373ff79fc} #define NS_ISCROLLPOSITIONLISTENER_IID \ - { 0x98a0c040, 0x09cf, 0x408b, \ - { 0xb5, 0x5f, 0x32, 0x1b, 0x4f, 0x8d, 0x9d, 0x67 } } +{ 0xf8dfc500, 0x6ad1, 0x11d3, { 0x83, 0x60, 0xa3, 0xf3, 0x73, 0xff, 0x79, 0xfc } } /** * Provides a way for a client of an nsIScrollableView to learn about scroll position @@ -62,7 +60,6 @@ class nsIScrollPositionListener : public nsISupports { NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLPOSITIONLISTENER_IID) NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) = 0; - virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) = 0; NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) = 0; }; diff --git a/view/src/nsScrollPortView.cpp b/view/src/nsScrollPortView.cpp index 3754171039c7e..0fb774310ff49 100644 --- a/view/src/nsScrollPortView.cpp +++ b/view/src/nsScrollPortView.cpp @@ -647,18 +647,6 @@ NS_IMETHODIMP nsScrollPortView::ScrollToImpl(nscoord aX, nscoord aY, PRUint32 aU // so don't update their positions scrolledView->SetPositionIgnoringChildWidgets(-aX, -aY); - // notify the listeners. - if (nsnull != mListeners) { - if (NS_SUCCEEDED(mListeners->Count(&listenerCount))) { - for (PRUint32 i = 0; i < listenerCount; i++) { - if (NS_SUCCEEDED(mListeners->QueryElementAt(i, kScrollPositionListenerIID, (void**)&listener))) { - listener->ViewPositionDidChange(this); - NS_RELEASE(listener); - } - } - } - } - nsPoint twipsDelta(aX - mOffsetX, aY - mOffsetY); // store the new position