Bug 364719 - "Resizers of images are positioned wrongly when page is scrolled" [p=mfenniak-moz@mathieu.fenniak.net (Mathieu Fenniak) / chris@pearce.org.nz (Chris Pearce [cpearce]) r=peterv r+sr=roc a=blocking1.9+]

This commit is contained in:
reed%reedloden.com 2008-01-22 07:39:07 +00:00
Родитель 0276cc5197
Коммит ed491d1146
8 изменённых файлов: 134 добавлений и 88 удалений

Просмотреть файл

@ -106,7 +106,7 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
nsCOMPtr<nsIDOMNode> resultNode;
do {
while (!resultNode && !nsEditor::NodeIsType(node, nsEditProperty::html)) {
res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
positionStr);
if (NS_FAILED(res)) return res;
@ -118,8 +118,7 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
if (NS_FAILED(res)) return res;
node.swap(parentNode);
}
} while (!resultNode &&
!nsEditor::NodeIsType(node, nsEditProperty::html));
}
element = do_QueryInterface(resultNode );
*_retval = element;
@ -315,16 +314,16 @@ nsHTMLEditor::HideGrabber()
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
// get the root content node.
nsCOMPtr<nsIDOMNode> parentNode;
res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsIDOMElement *rootElement = GetRoot();
nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
if (!parentContent) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(rootElement);
if (!rootContent) return NS_ERROR_NULL_POINTER;
DeleteRefToAnonymousNode(mGrabber, rootContent, ps);
DeleteRefToAnonymousNode(mGrabber, parentContent, ps);
mGrabber = nsnull;
DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps);
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
mPositioningShadow = nsnull;
return NS_OK;
@ -346,11 +345,13 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
// first, let's keep track of that element...
mAbsolutelyPositionedObject = aElement;
nsIDOMElement *rootElement = GetRoot();
if (!rootElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> parentNode;
res = aElement->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
res = CreateGrabber(parentNode, getter_AddRefs(mGrabber));
NS_ENSURE_SUCCESS(res, res);
res = CreateGrabber(rootElement, getter_AddRefs(mGrabber));
if (NS_FAILED(res)) return res;
// and set its position
return RefreshGrabber();
}
@ -358,16 +359,17 @@ nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
nsresult
nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
{
nsIDOMElement *rootElement = GetRoot();
if (!rootElement) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> parentNode;
nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
// now, let's create the resizing shadow
nsresult result = CreateShadow(getter_AddRefs(mPositioningShadow),
rootElement, mAbsolutelyPositionedObject);
if (NS_FAILED(result)) return result;
result = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
res = CreateShadow(getter_AddRefs(mPositioningShadow),
parentNode, mAbsolutelyPositionedObject);
NS_ENSURE_SUCCESS(res,res);
res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
mPositionedObjectX, mPositionedObjectY);
if (NS_FAILED(result)) return result;
NS_ENSURE_SUCCESS(res,res);
// make the shadow appear
mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
@ -381,7 +383,7 @@ nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
mPositionedObjectHeight);
mIsMoving = PR_TRUE;
return result;
return res;
}
void
@ -421,14 +423,15 @@ nsHTMLEditor::EndMoving()
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
// get the root content node.
nsCOMPtr<nsIDOMNode> parentNode;
nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsIDOMElement *rootElement = GetRoot();
nsCOMPtr<nsIContent> parentContent( do_QueryInterface(parentNode) );
if (!parentContent) return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> rootContent( do_QueryInterface(rootElement) );
if (!rootContent) return NS_ERROR_FAILURE;
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps);
mPositioningShadow = nsnull;
}
nsCOMPtr<nsPIDOMEventTarget> piTarget = GetPIDOMEventTarget();

Просмотреть файл

@ -203,8 +203,18 @@ nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
aShell->GetPresContext()->GetPresShell() == aShell) {
nsCOMPtr<nsIDocumentObserver> docObserver = do_QueryInterface(aShell);
if (docObserver) {
// Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
// knows we're messing with the frame tree.
nsCOMPtr<nsIDOMDocument> domDocument;
nsresult res = GetDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
if (document)
docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
docObserver->ContentRemoved(content->GetCurrentDoc(),
aParentContent, content, -1);
if (document)
docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
}
}
content->UnbindFromTree();

Просмотреть файл

@ -5800,34 +5800,21 @@ nsHTMLEditor::CopyLastEditableChildStyles(nsIDOMNode * aPreviousBlock, nsIDOMNod
nsresult
nsHTMLEditor::GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY)
{
// we are going to need the PresShell
aX = 0;
aY = 0;
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
nsIFrame *frame = ps->GetPrimaryFrameFor(content); // not ref-counted
nsIFrame *frame = ps->GetPrimaryFrameFor(content);
if (nsHTMLEditUtils::IsHR(aElement) && frame) {
frame = frame->GetNextSibling();
}
PRInt32 offsetX = 0, offsetY = 0;
while (frame) {
// Look for a widget so we can get screen coordinates
nsIView* view = frame->GetViewExternal();
if (view && view->HasWidget())
break;
// No widget yet, so count up the coordinates of the frame
nsPoint origin = frame->GetPosition();
offsetX += origin.x;
offsetY += origin.y;
frame = frame->GetParent();
}
aX = nsPresContext::AppUnitsToIntCSSPixels(offsetX);
aY = nsPresContext::AppUnitsToIntCSSPixels(offsetY);
nsIFrame *container = ps->GetAbsoluteContainingBlock(frame);
if (!frame) return NS_OK;
nsPoint off = frame->GetOffsetTo(container);
aX = nsPresContext::AppUnitsToIntCSSPixels(off.x);
aY = nsPresContext::AppUnitsToIntCSSPixels(off.y);
return NS_OK;
}

Просмотреть файл

@ -815,6 +815,8 @@ protected:
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsIContent * aParentContent,
nsIPresShell* aShell);
// Returns the offset of an element's frame to its absolute containing block.
nsresult GetElementOrigin(nsIDOMElement * aElement, PRInt32 & aX, PRInt32 & aY);
nsresult GetPositionAndDimensions(nsIDOMElement * aElement,
PRInt32 & aX, PRInt32 & aY,

Просмотреть файл

@ -338,37 +338,37 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
NS_ENSURE_ARG_POINTER(aResizedElement);
mResizedObject = aResizedElement;
// the resizers and the shadow will be anonymous children of the body
nsIDOMElement *bodyElement = GetRoot();
if (!bodyElement) return NS_ERROR_NULL_POINTER;
// let's create the resizers
// The resizers and the shadow will be anonymous siblings of the element.
nsresult res;
nsCOMPtr<nsIDOMNode> parentNode;
res = aResizedElement->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
res = CreateResizer(getter_AddRefs(mTopLeftHandle),
nsIHTMLObjectResizer::eTopLeft, bodyElement);
nsIHTMLObjectResizer::eTopLeft, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mTopHandle),
nsIHTMLObjectResizer::eTop, bodyElement);
nsIHTMLObjectResizer::eTop, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mTopRightHandle),
nsIHTMLObjectResizer::eTopRight, bodyElement);
nsIHTMLObjectResizer::eTopRight, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mLeftHandle),
nsIHTMLObjectResizer::eLeft, bodyElement);
nsIHTMLObjectResizer::eLeft, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mRightHandle),
nsIHTMLObjectResizer::eRight, bodyElement);
nsIHTMLObjectResizer::eRight, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mBottomLeftHandle),
nsIHTMLObjectResizer::eBottomLeft, bodyElement);
nsIHTMLObjectResizer::eBottomLeft, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mBottomHandle),
nsIHTMLObjectResizer::eBottom, bodyElement);
nsIHTMLObjectResizer::eBottom, parentNode);
if (NS_FAILED(res)) return res;
res = CreateResizer(getter_AddRefs(mBottomRightHandle),
nsIHTMLObjectResizer::eBottomRight, bodyElement);
nsIHTMLObjectResizer::eBottomRight, parentNode);
if (NS_FAILED(res)) return res;
res = GetPositionAndDimensions(aResizedElement,
@ -387,7 +387,7 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
if (NS_FAILED(res)) return res;
// now, let's create the resizing shadow
res = CreateShadow(getter_AddRefs(mResizingShadow), bodyElement,
res = CreateShadow(getter_AddRefs(mResizingShadow), parentNode,
aResizedElement);
if (NS_FAILED(res)) return res;
// and set its position
@ -396,7 +396,7 @@ nsHTMLEditor::ShowResizers(nsIDOMElement *aResizedElement)
if (NS_FAILED(res)) return res;
// and then the resizing info tooltip
res = CreateResizingInfo(getter_AddRefs(mResizingInfo), bodyElement);
res = CreateResizingInfo(getter_AddRefs(mResizingInfo), parentNode);
if (NS_FAILED(res)) return res;
@ -428,60 +428,58 @@ nsHTMLEditor::HideResizers(void)
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
// get the root content node.
nsIDOMElement *bodyElement = GetRoot();
nsCOMPtr<nsIContent> bodyContent( do_QueryInterface(bodyElement) );
if (!bodyContent) return NS_ERROR_FAILURE;
nsresult res;
nsCOMPtr<nsIDOMNode> parentNode;
res = mTopLeftHandle->GetParentNode(getter_AddRefs(parentNode));
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mTopLeftHandle, bodyContent, ps);
mTopLeftHandle, parentContent, ps);
mTopLeftHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mTopHandle, bodyContent, ps);
mTopHandle, parentContent, ps);
mTopHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mTopRightHandle, bodyContent, ps);
mTopRightHandle, parentContent, ps);
mTopRightHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mLeftHandle, bodyContent, ps);
mLeftHandle, parentContent, ps);
mLeftHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mRightHandle, bodyContent, ps);
mRightHandle, parentContent, ps);
mRightHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mBottomLeftHandle, bodyContent, ps);
mBottomLeftHandle, parentContent, ps);
mBottomLeftHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mBottomHandle, bodyContent, ps);
mBottomHandle, parentContent, ps);
mBottomHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mBottomRightHandle, bodyContent, ps);
mBottomRightHandle, parentContent, ps);
mBottomRightHandle = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mResizingShadow, bodyContent, ps);
mResizingShadow, parentContent, ps);
mResizingShadow = nsnull;
RemoveListenerAndDeleteRef(mousedown, mMouseListenerP, PR_TRUE,
mResizingInfo, bodyContent, ps);
mResizingInfo, parentContent, ps);
mResizingInfo = nsnull;
// don't forget to remove the listeners !
nsCOMPtr<nsPIDOMEventTarget> piTarget = GetPIDOMEventTarget();
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(piTarget);
nsresult res;
if (target && mMouseMotionListenerP)
{
@ -683,10 +681,45 @@ nsHTMLEditor::SetResizingInfoPosition(PRInt32 aX, PRInt32 aY, PRInt32 aW, PRInt3
NS_NAMED_LITERAL_STRING(leftStr, "left");
NS_NAMED_LITERAL_STRING(topStr, "top");
// Determine the position of the resizing info box based upon the new
// position and size of the element (aX, aY, aW, aH), and which
// resizer is the "activated handle". For example, place the resizing
// info box at the bottom-right corner of the new element, if the element
// is being resized by the bottom-right resizer.
PRInt32 infoXPosition;
PRInt32 infoYPosition;
if (mActivatedHandle == mTopLeftHandle ||
mActivatedHandle == mLeftHandle ||
mActivatedHandle == mBottomLeftHandle)
infoXPosition = aX;
else if (mActivatedHandle == mTopHandle ||
mActivatedHandle == mBottomHandle)
infoXPosition = aX + (aW / 2);
else
// should only occur when mActivatedHandle is one of the 3 right-side
// handles, but this is a reasonable default if it isn't any of them (?)
infoXPosition = aX + aW;
if (mActivatedHandle == mTopLeftHandle ||
mActivatedHandle == mTopHandle ||
mActivatedHandle == mTopRightHandle)
infoYPosition = aY;
else if (mActivatedHandle == mLeftHandle ||
mActivatedHandle == mRightHandle)
infoYPosition = aY + (aH / 2);
else
// should only occur when mActivatedHandle is one of the 3 bottom-side
// handles, but this is a reasonable default if it isn't any of them (?)
infoYPosition = aY + aH;
// Offset info box by 20 so it's not directly under the mouse cursor.
const int mouseCursorOffset = 20;
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, leftStr,
aX + mInfoXIncrement);
infoXPosition + mouseCursorOffset);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingInfo, topStr,
aY + mInfoYIncrement);
infoYPosition + mouseCursorOffset);
nsCOMPtr<nsIDOMNode> textInfo;
nsresult res = mResizingInfo->GetFirstChild(getter_AddRefs(textInfo));
@ -840,15 +873,17 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
mouseEvent->GetClientX(&clientX);
mouseEvent->GetClientY(&clientY);
PRInt32 newX = GetNewResizingX(clientX, clientY);
PRInt32 newY = GetNewResizingY(clientX, clientY);
PRInt32 newWidth = GetNewResizingWidth(clientX, clientY);
PRInt32 newHeight = GetNewResizingHeight(clientX, clientY);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
leftStr,
GetNewResizingX(clientX, clientY));
newX);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
topStr,
GetNewResizingY(clientX, clientY));
newY);
mHTMLCSSUtils->SetCSSPropertyPixels(mResizingShadow,
NS_LITERAL_STRING("width"),
newWidth);
@ -856,7 +891,7 @@ nsHTMLEditor::MouseMove(nsIDOMEvent* aMouseEvent)
NS_LITERAL_STRING("height"),
newHeight);
return SetResizingInfoPosition(clientX, clientY, newWidth, newHeight);
return SetResizingInfoPosition(newX, newY, newWidth, newHeight);
}
if (mGrabberClicked) {

Просмотреть файл

@ -723,14 +723,16 @@ private:
nsIFrame* GetFrameFor(nsIContent* aContent);
/**
* These functions are used when we start frame creation from a non-root
* These two functions are used when we start frame creation from a non-root
* element. They should recreate the same state that we would have
* arrived at if we had built frames from the root frame to aFrame.
* Therefore, any calls to PushFloatContainingBlock and
* PushAbsoluteContainingBlock during frame construction should get
* corresponding logic in these functions.
*/
public:
nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
private:
nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame);
nsIContent* PropagateScrollToViewport();

Просмотреть файл

@ -645,6 +645,8 @@ public:
*/
static PRInt32 GetVerifyReflowFlags();
virtual nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
#ifdef MOZ_REFLOW_PERF
NS_IMETHOD DumpReflows() = 0;
NS_IMETHOD CountReflows(const char * aName, nsIFrame * aFrame) = 0;

Просмотреть файл

@ -7662,3 +7662,8 @@ void ColorToString(nscolor aColor, nsAutoString &aString)
NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor));
CopyASCIItoUTF16(buf, aString);
}
nsIFrame* nsIPresShell::GetAbsoluteContainingBlock(nsIFrame *aFrame)
{
return FrameConstructor()->GetAbsoluteContainingBlock(aFrame);
}