зеркало из https://github.com/mozilla/gecko-dev.git
Fixing bug 81290. The element.offsetXXX properties contained incorrect values when the element is positioned, or a child of a positioned element, this made these properties kinda useless since we were nowhere close to IE wrt the values of these properties. r=pollmann@netscape.com, sr=vidur@netscape.com
This commit is contained in:
Родитель
c47e29468b
Коммит
b0304d8e85
|
@ -29,7 +29,7 @@
|
||||||
#include "nsICSSDeclaration.h"
|
#include "nsICSSDeclaration.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIDocumentEncoder.h"
|
#include "nsIDocumentEncoder.h"
|
||||||
#include "nsIDOMDocumentFragment.h"
|
#include "nsIDOMHTMLDocument.h"
|
||||||
#include "nsIDOMAttr.h"
|
#include "nsIDOMAttr.h"
|
||||||
#include "nsIDOMEventReceiver.h"
|
#include "nsIDOMEventReceiver.h"
|
||||||
#include "nsIDOMNamedNodeMap.h"
|
#include "nsIDOMNamedNodeMap.h"
|
||||||
|
@ -413,7 +413,7 @@ class nsGenericHTMLElementTearoff : public nsIDOMNSHTMLElement,
|
||||||
NS_ADDREF(mElement);
|
NS_ADDREF(mElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
~nsGenericHTMLElementTearoff()
|
virtual ~nsGenericHTMLElementTearoff()
|
||||||
{
|
{
|
||||||
NS_RELEASE(mElement);
|
NS_RELEASE(mElement);
|
||||||
}
|
}
|
||||||
|
@ -732,121 +732,217 @@ nsGenericHTMLElement::GetOffsetRect(nsRect& aRect,
|
||||||
nsIAtom* aOffsetParentTag,
|
nsIAtom* aOffsetParentTag,
|
||||||
nsIContent** aOffsetParent)
|
nsIContent** aOffsetParent)
|
||||||
{
|
{
|
||||||
nsresult res = NS_OK;
|
|
||||||
|
|
||||||
*aOffsetParent = nsnull;
|
*aOffsetParent = nsnull;
|
||||||
|
|
||||||
aRect.x = aRect.y = 0;
|
aRect.x = aRect.y = 0;
|
||||||
aRect.Empty();
|
aRect.Empty();
|
||||||
|
|
||||||
if(mDocument) {
|
if (!mDocument) {
|
||||||
// Get Presentation shell 0
|
return NS_OK;
|
||||||
nsCOMPtr<nsIPresShell> presShell;
|
}
|
||||||
mDocument->GetShellAt(0, getter_AddRefs(presShell));
|
|
||||||
|
|
||||||
if(presShell) {
|
// Get Presentation shell 0
|
||||||
// Flush all pending notifications so that our frames are uptodate
|
nsCOMPtr<nsIPresShell> presShell;
|
||||||
mDocument->FlushPendingNotifications();
|
mDocument->GetShellAt(0, getter_AddRefs(presShell));
|
||||||
|
|
||||||
// Get the Frame for our content
|
if (!presShell) {
|
||||||
nsIFrame* frame = nsnull;
|
return NS_OK;
|
||||||
presShell->GetPrimaryFrameFor(this, &frame);
|
}
|
||||||
if(frame != nsnull) {
|
|
||||||
// Get it's origin
|
|
||||||
nsPoint origin;
|
|
||||||
frame->GetOrigin(origin);
|
|
||||||
|
|
||||||
// Get the union of all rectangles in this and continuation frames
|
// Get the Presentation Context from the Shell
|
||||||
nsRect rcFrame;
|
nsCOMPtr<nsIPresContext> context;
|
||||||
nsIFrame* next = frame;
|
presShell->GetPresContext(getter_AddRefs(context));
|
||||||
do {
|
|
||||||
nsRect rect;
|
if (!context) {
|
||||||
next->GetRect(rect);
|
return NS_OK;
|
||||||
rcFrame.UnionRect(rcFrame, rect);
|
}
|
||||||
next->GetNextInFlow(&next);
|
|
||||||
} while (nsnull != next);
|
// 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
|
nsCOMPtr<nsIContent> docElement;
|
||||||
// the tagName passed in or is the document element.
|
mDocument->GetRootContent(getter_AddRefs(docElement));
|
||||||
nsCOMPtr<nsIContent> docElement;
|
|
||||||
mDocument->GetRootContent(getter_AddRefs(docElement));
|
|
||||||
nsIFrame* parent = frame;
|
|
||||||
nsCOMPtr<nsIContent> 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<nsIAtom> 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);
|
|
||||||
|
|
||||||
break;
|
// Find the frame parent whose content's tagName either matches
|
||||||
}
|
// the tagName passed in or is the document element.
|
||||||
}
|
nsCOMPtr<nsIContent> content;
|
||||||
// Add the parent's origin to our own to get to the
|
nsIFrame* parent = nsnull;
|
||||||
// right coordinate system
|
PRBool done = PR_FALSE;
|
||||||
nsPoint parentOrigin;
|
nsCOMPtr<nsIAtom> tag;
|
||||||
parent->GetOrigin(parentOrigin);
|
|
||||||
origin += parentOrigin;
|
|
||||||
|
|
||||||
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
|
content->GetTag(*getter_AddRefs(tag));
|
||||||
const nsStyleBorder* border;
|
|
||||||
nsStyleCoord coord;
|
// If the tag of this frame matches the one passed in, break here
|
||||||
frame->GetStyleData(eStyleStruct_Border, (const nsStyleStruct*&)border);
|
if (tag.get() == aOffsetParentTag) {
|
||||||
if (border) {
|
if (parent != frame) {
|
||||||
if (eStyleUnit_Coord == border->mBorder.GetLeftUnit()) {
|
*aOffsetParent = content;
|
||||||
origin.x += border->mBorder.GetLeft(coord).GetCoordValue();
|
NS_ADDREF(*aOffsetParent);
|
||||||
}
|
|
||||||
if (eStyleUnit_Coord == border->mBorder.GetTopUnit()) {
|
|
||||||
origin.y += border->mBorder.GetTop(coord).GetCoordValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// And subtract out the border for the parent
|
parent->GetParent(&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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Presentation Context from the Shell
|
if (is_absolutely_positioned && !*aOffsetParent) {
|
||||||
nsCOMPtr<nsIPresContext> context;
|
// If this element is absolutely positioned, but we don't have
|
||||||
presShell->GetPresContext(getter_AddRefs(context));
|
// 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) {
|
nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(mDocument));
|
||||||
// Get the scale from that Presentation Context
|
|
||||||
float scale;
|
|
||||||
context->GetTwipsToPixels(&scale);
|
|
||||||
|
|
||||||
// Convert to pixels using that scale
|
if (html_doc) {
|
||||||
aRect.x = NSTwipsToIntPixels(origin.x, scale);
|
nsCOMPtr<nsIDOMHTMLElement> html_element;
|
||||||
aRect.y = NSTwipsToIntPixels(origin.y, scale);
|
|
||||||
aRect.width = NSTwipsToIntPixels(rcFrame.width, scale);
|
html_doc->GetBody(getter_AddRefs(html_element));
|
||||||
aRect.height = NSTwipsToIntPixels(rcFrame.height, scale);
|
|
||||||
|
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
|
nsresult
|
||||||
|
|
Загрузка…
Ссылка в новой задаче