diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index 12dde33ddc5..4e851c91a61 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -142,6 +142,7 @@ #include "nsIEditor.h" #include "nsIEditorIMESupport.h" #include "nsEventDispatcher.h" +#include "nsLayoutUtils.h" // XXX todo: add in missing out-of-memory checks @@ -625,20 +626,7 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent) } // Get the union of all rectangles in this and continuation frames - nsRect rcFrame; - nsIFrame* next = frame; - - do { - rcFrame.UnionRect(rcFrame, next->GetRect()); - next = next->GetNextContinuation(); - } while (next); - - if (rcFrame.IsEmpty()) { - // It could happen that all the rects are empty (eg zero-width or - // zero-height). In that case, use the first rect for the frame. - rcFrame = frame->GetRect(); - } - + nsRect rcFrame = nsLayoutUtils::GetUnionOfAllRects(frame); nsIContent *docElement = document->GetRootContent(); // Find the frame parent whose content's tagName either matches @@ -662,7 +650,7 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent) PRBool is_absolutely_positioned = PR_FALSE; PRBool is_positioned = PR_FALSE; - origin = frame->GetPosition(); + origin = nsLayoutUtils::GetPositionIgnoringScrolling(frame); const nsStyleDisplay* display = frame->GetStyleDisplay(); @@ -698,7 +686,7 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent) // right coordinate system if (!is_absolutely_positioned) { - origin += parent->GetPosition(); + origin += nsLayoutUtils::GetPositionIgnoringScrolling(parent); } content = parent->GetContent(); diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp index adc0f286c7f..ea692c03ce5 100644 --- a/mozilla/layout/base/nsLayoutUtils.cpp +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -473,6 +473,47 @@ nsLayoutUtils::GetNearestScrollingView(nsIView* aView, Direction aDirection) return scrollableView; } +nsPoint +nsLayoutUtils::GetPositionIgnoringScrolling(nsIFrame* aFrame) +{ + nsIFrame* parent = aFrame->GetParent(); + if (!parent) + return aFrame->GetPosition(); + nsIScrollableFrame* scrollable; + CallQueryInterface(parent, &scrollable); + if (!scrollable) + return aFrame->GetPosition(); + // Compensate for the scroll position ... this might not result in (0,0) + // if there is a scrollbar above or to the left of the content. Note that + // scrolling moves the frame's position by the negative of GetScrollPosition. + return aFrame->GetPosition() + scrollable->GetScrollPosition(); +} + +nsRect +nsLayoutUtils::GetUnionOfAllRects(nsIFrame* aFrame) +{ + nsRect rcFrame; + nsIFrame* next = aFrame; + nsIFrame* frameParent = aFrame->GetParent(); + if (!frameParent) + return aFrame->GetRect(); + + do { + nsRect r = next->GetRect() + next->GetParent()->GetOffsetTo(frameParent); + rcFrame.UnionRect(rcFrame, r); + next = next->GetNextContinuation(); + } while (next); + + if (rcFrame.IsEmpty()) { + // It could happen that all the rects are empty (eg zero-width or + // zero-height). In that case, use the first rect for the frame, so the + // x and y coordinates are usable. + rcFrame = aFrame->GetRect(); + } + + return rcFrame; +} + nsPoint nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(nsIDOMEvent* aDOMEvent, nsIFrame* aFrame) { diff --git a/mozilla/layout/base/nsLayoutUtils.h b/mozilla/layout/base/nsLayoutUtils.h index dfc8bc56be4..b2637c3adbb 100644 --- a/mozilla/layout/base/nsLayoutUtils.h +++ b/mozilla/layout/base/nsLayoutUtils.h @@ -261,6 +261,19 @@ public: * its pres-shell */ static PRBool IsInitialContainingBlock(nsIFrame* aFrame); + + /** + * @return the offset of aFrame from its parent, as if it were scrolled to + * the top. + */ + static nsPoint GetPositionIgnoringScrolling(nsIFrame* aFrame); + + /** + * @return a rectangle relative to aFrame's parent that is the union of + * aFrame->GetRect() plus the GetRect()s of all aFrame's continuations. If + * all the rects are empty we just return aFrame->GetRect(). + */ + static nsRect GetUnionOfAllRects(nsIFrame* aFrame); /** * Get the coordinates of a given DOM mouse event, relative to a given diff --git a/mozilla/layout/xul/base/src/nsBoxObject.cpp b/mozilla/layout/xul/base/src/nsBoxObject.cpp index 1435fb036ab..aa73fea52a3 100644 --- a/mozilla/layout/xul/base/src/nsBoxObject.cpp +++ b/mozilla/layout/xul/base/src/nsBoxObject.cpp @@ -56,6 +56,7 @@ #include "nsIWidget.h" #include "nsIDOMXULElement.h" #include "nsIFrame.h" +#include "nsLayoutUtils.h" // Static IIDs/CIDs. Try to minimize these. static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); @@ -195,15 +196,10 @@ nsBoxObject::GetOffsetRect(nsRect& aRect) nsIFrame* frame = GetFrame(PR_TRUE); if (frame) { // Get its origin - nsPoint origin = frame->GetPosition(); + nsPoint origin = nsLayoutUtils::GetPositionIgnoringScrolling(frame); // Get the union of all rectangles in this and continuation frames - nsRect rcFrame; - nsIFrame* next = frame; - do { - rcFrame.UnionRect(rcFrame, next->GetRect()); - next = next->GetNextContinuation(); - } while (nsnull != next); + nsRect rcFrame = nsLayoutUtils::GetUnionOfAllRects(frame); // Find the frame parent whose content is the document element. nsIContent *docElement = mContent->GetCurrentDoc()->GetRootContent(); @@ -216,7 +212,7 @@ nsBoxObject::GetOffsetRect(nsRect& aRect) // Add the parent's origin to our own to get to the // right coordinate system - origin += parent->GetPosition(); + origin += nsLayoutUtils::GetPositionIgnoringScrolling(parent); parent = parent->GetParent(); }