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();
}