diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp
index 64a123a2b14c..3510b8c6a58d 100644
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -29,7 +29,7 @@
#include "nsICSSDeclaration.h"
#include "nsIDocument.h"
#include "nsIDocumentEncoder.h"
-#include "nsIDOMDocumentFragment.h"
+#include "nsIDOMHTMLDocument.h"
#include "nsIDOMAttr.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMNamedNodeMap.h"
@@ -413,7 +413,7 @@ class nsGenericHTMLElementTearoff : public nsIDOMNSHTMLElement,
NS_ADDREF(mElement);
}
- ~nsGenericHTMLElementTearoff()
+ virtual ~nsGenericHTMLElementTearoff()
{
NS_RELEASE(mElement);
}
@@ -732,121 +732,217 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect,
nsIAtom* aOffsetParentTag,
nsIContent** aOffsetParent)
{
- nsresult res = NS_OK;
-
*aOffsetParent = nsnull;
aRect.x = aRect.y = 0;
aRect.Empty();
- if(mDocument) {
- // Get Presentation shell 0
- nsCOMPtr presShell;
- mDocument->GetShellAt(0, getter_AddRefs(presShell));
+ if (!mDocument) {
+ return NS_OK;
+ }
- if(presShell) {
- // Flush all pending notifications so that our frames are uptodate
- mDocument->FlushPendingNotifications();
+ // Get Presentation shell 0
+ nsCOMPtr presShell;
+ mDocument->GetShellAt(0, getter_AddRefs(presShell));
- // Get the Frame for our content
- nsIFrame* frame = nsnull;
- presShell->GetPrimaryFrameFor(this, &frame);
- if(frame != nsnull) {
- // Get it's origin
- nsPoint origin;
- frame->GetOrigin(origin);
+ if (!presShell) {
+ return NS_OK;
+ }
- // Get the union of all rectangles in this and continuation frames
- nsRect rcFrame;
- nsIFrame* next = frame;
- do {
- nsRect rect;
- next->GetRect(rect);
- rcFrame.UnionRect(rcFrame, rect);
- next->GetNextInFlow(&next);
- } while (nsnull != next);
+ // Get the Presentation Context from the Shell
+ nsCOMPtr context;
+ presShell->GetPresContext(getter_AddRefs(context));
+
+ if (!context) {
+ return NS_OK;
+ }
+
+ // Flush all pending notifications so that our frames are uptodate
+ mDocument->FlushPendingNotifications();
+
+ // Get the Frame for our content
+ nsIFrame* frame = nsnull;
+ presShell->GetPrimaryFrameFor(this, &frame);
+
+ if (!frame) {
+ return NS_OK;
+ }
+
+ // Get the union of all rectangles in this and continuation frames
+ nsRect rcFrame;
+ nsIFrame* next = frame;
+
+ do {
+ nsRect rect;
+ next->GetRect(rect);
+
+ rcFrame.UnionRect(rcFrame, rect);
+
+ next->GetNextInFlow(&next);
+ } while (next);
- // Find the frame parent whose content's tagName either matches
- // the tagName passed in or is the document element.
- nsCOMPtr docElement;
- mDocument->GetRootContent(getter_AddRefs(docElement));
- nsIFrame* parent = frame;
- nsCOMPtr parentContent;
- frame->GetParent(&parent);
- while (parent) {
- parent->GetContent(getter_AddRefs(parentContent));
- if (parentContent) {
- // If we've hit the document element, break here
- if (parentContent.get() == docElement.get()) {
- break;
- }
- nsCOMPtr tag;
- // If the tag of this frame matches the one passed in, break here
- parentContent->GetTag(*getter_AddRefs(tag));
- if (tag.get() == aOffsetParentTag) {
- *aOffsetParent = parentContent;
- NS_IF_ADDREF(*aOffsetParent);
+ nsCOMPtr docElement;
+ mDocument->GetRootContent(getter_AddRefs(docElement));
- break;
- }
- }
- // Add the parent's origin to our own to get to the
- // right coordinate system
- nsPoint parentOrigin;
- parent->GetOrigin(parentOrigin);
- origin += parentOrigin;
+ // Find the frame parent whose content's tagName either matches
+ // the tagName passed in or is the document element.
+ nsCOMPtr content;
+ nsIFrame* parent = nsnull;
+ PRBool done = PR_FALSE;
+ nsCOMPtr tag;
- parent->GetParent(&parent);
+
+ frame->GetContent(getter_AddRefs(content));
+
+ if (content) {
+ content->GetTag(*getter_AddRefs(tag));
+
+ if (tag.get() == aOffsetParentTag || content == docElement) {
+ done = PR_TRUE;
+
+ parent = frame;
+ }
+ }
+
+ const nsStyleDisplay* display = nsnull;
+ nsPoint origin(0, 0);
+
+ if (!done) {
+ PRBool is_absolutely_positioned = PR_FALSE;
+
+ frame->GetOrigin(origin);
+
+ frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
+
+ if (display && display->IsAbsolutelyPositioned()) {
+ // If the primary frame or a parent is absolutely positioned
+ // (fixed or absolute) we stop walking up the frame parent
+ // chain
+
+ is_absolutely_positioned = PR_TRUE;
+ }
+
+ frame->GetParent(&parent);
+
+ while (parent) {
+ parent->GetStyleData(eStyleStruct_Display,
+ (const nsStyleStruct*&)display);
+
+ if (display) {
+ if (display->IsPositioned()) {
+ // Stop at the first *parent* that is positioned (fixed,
+ // absolute, or relatiive)
+
+ parent->GetContent(aOffsetParent);
+
+ break;
+ }
+ }
+
+ // Add the parent's origin to our own to get to the
+ // right coordinate system
+
+ if (!is_absolutely_positioned) {
+ nsPoint parentOrigin;
+ parent->GetOrigin(parentOrigin);
+ origin += parentOrigin;
+ }
+
+ parent->GetContent(getter_AddRefs(content));
+
+ if (content) {
+ // If we've hit the document element, break here
+ if (content == docElement) {
+ break;
}
- // For the origin, add in the border for the frame
- const nsStyleBorder* border;
- nsStyleCoord coord;
- frame->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)border);
- if (border) {
- if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) {
- origin.x += border->mBorder.GetLeft(coord).GetCoordValue();
- }
- if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) {
- origin.y += border->mBorder.GetTop(coord).GetCoordValue();
+ content->GetTag(*getter_AddRefs(tag));
+
+ // If the tag of this frame matches the one passed in, break here
+ if (tag.get() == aOffsetParentTag) {
+ if (parent != frame) {
+ *aOffsetParent = content;
+ NS_ADDREF(*aOffsetParent);
}
+
+ break;
}
+ }
- // And subtract out the border for the parent
- if (parent) {
- const nsStyleBorder* parentBorder;
- parent->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)parentBorder);
- if (parentBorder) {
- if (eStyleUnit_Coord == parentBorder->mBorder.GetLeftUnit()) {
- origin.x -= parentBorder->mBorder.GetLeft(coord).GetCoordValue();
- }
- if (eStyleUnit_Coord == parentBorder->mBorder.GetTopUnit()) {
- origin.y -= parentBorder->mBorder.GetTop(coord).GetCoordValue();
- }
- }
- }
+ parent->GetParent(&parent);
+ }
- // Get the Presentation Context from the Shell
- nsCOMPtr context;
- presShell->GetPresContext(getter_AddRefs(context));
+ if (is_absolutely_positioned && !*aOffsetParent) {
+ // If this element is absolutely positioned, but we don't have
+ // an offset parent it means this element is an absolutely
+ // positioned child that's not nested inside another positioned
+ // element, in this case the element's frame's parent is the
+ // frame for the HTML element so we fail to find the body in the
+ // parent chain. We want the offset parent in this case to be
+ // the body, so we just get the body element from the document.
- if(context) {
- // Get the scale from that Presentation Context
- float scale;
- context->GetTwipsToPixels(&scale);
+ nsCOMPtr html_doc(do_QueryInterface(mDocument));
- // Convert to pixels using that scale
- aRect.x = NSTwipsToIntPixels(origin.x, scale);
- aRect.y = NSTwipsToIntPixels(origin.y, scale);
- aRect.width = NSTwipsToIntPixels(rcFrame.width, scale);
- aRect.height = NSTwipsToIntPixels(rcFrame.height, scale);
+ if (html_doc) {
+ nsCOMPtr html_element;
+
+ html_doc->GetBody(getter_AddRefs(html_element));
+
+ if (html_element) {
+ CallQueryInterface(html_element, aOffsetParent);
}
}
}
}
- return res;
+ // For the origin, add in the border for the frame
+ const nsStyleBorder* border = nsnull;
+ nsStyleCoord coord;
+
+#if 0
+ // We used to do this to include the border of the frame in the
+ // calculations, but I think that's wrong. My tests show that we
+ // work more like IE if we don't do this, so lets try this and see
+ // if people agree.
+ frame->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)border);
+
+ if (border) {
+ if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) {
+ origin.x += border->mBorder.GetLeft(coord).GetCoordValue();
+ }
+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) {
+ origin.y += border->mBorder.GetTop(coord).GetCoordValue();
+ }
+ }
+#endif
+
+ // And subtract out the border for the parent
+ if (parent) {
+ border = nsnull;
+
+ parent->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)border);
+ if (border) {
+ if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) {
+ origin.x -= border->mBorder.GetLeft(coord).GetCoordValue();
+ }
+ if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) {
+ origin.y -= border->mBorder.GetTop(coord).GetCoordValue();
+ }
+ }
+ }
+
+ // Get the scale from that Presentation Context
+ float scale;
+ context->GetTwipsToPixels(&scale);
+
+ // Convert to pixels using that scale
+ aRect.x = NSTwipsToIntPixels(origin.x, scale);
+ aRect.y = NSTwipsToIntPixels(origin.y, scale);
+ aRect.width = NSTwipsToIntPixels(rcFrame.width, scale);
+ aRect.height = NSTwipsToIntPixels(rcFrame.height, scale);
+
+ return NS_OK;
}
nsresult