diff --git a/mozilla/editor/libeditor/html/nsHTMLAbsPosition.cpp b/mozilla/editor/libeditor/html/nsHTMLAbsPosition.cpp index 3f9716d6a5d..aa06b289a83 100644 --- a/mozilla/editor/libeditor/html/nsHTMLAbsPosition.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLAbsPosition.cpp @@ -106,7 +106,7 @@ nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval) nsCOMPtr node = do_QueryInterface(element); nsCOMPtr 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 ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. + nsCOMPtr parentNode; + res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); - nsIDOMElement *rootElement = GetRoot(); + nsCOMPtr parentContent = do_QueryInterface(parentNode); + if (!parentContent) return NS_ERROR_NULL_POINTER; - nsCOMPtr 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 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 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 ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. + nsCOMPtr parentNode; + nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); - nsIDOMElement *rootElement = GetRoot(); + nsCOMPtr parentContent( do_QueryInterface(parentNode) ); + if (!parentContent) return NS_ERROR_FAILURE; - nsCOMPtr rootContent( do_QueryInterface(rootElement) ); - if (!rootContent) return NS_ERROR_FAILURE; + DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); - DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps); mPositioningShadow = nsnull; } nsCOMPtr piTarget = GetPIDOMEventTarget(); diff --git a/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp b/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp index d8f71067784..2dbdc6868af 100644 --- a/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLAnonymousUtils.cpp @@ -203,8 +203,18 @@ nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement, aShell->GetPresContext()->GetPresShell() == aShell) { nsCOMPtr docObserver = do_QueryInterface(aShell); if (docObserver) { + // Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell + // knows we're messing with the frame tree. + nsCOMPtr domDocument; + nsresult res = GetDocument(getter_AddRefs(domDocument)); + nsCOMPtr 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(); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 22f6931e4bb..694c6502b63 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -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 ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr 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; } diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 1ab4d1a62f3..2a1e91453b7 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -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, diff --git a/mozilla/editor/libeditor/html/nsHTMLObjectResizer.cpp b/mozilla/editor/libeditor/html/nsHTMLObjectResizer.cpp index f430752dfe6..eb84689fd64 100644 --- a/mozilla/editor/libeditor/html/nsHTMLObjectResizer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLObjectResizer.cpp @@ -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 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 ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // get the root content node. - - nsIDOMElement *bodyElement = GetRoot(); - - nsCOMPtr bodyContent( do_QueryInterface(bodyElement) ); - if (!bodyContent) return NS_ERROR_FAILURE; + nsresult res; + nsCOMPtr parentNode; + res = mTopLeftHandle->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_SUCCESS(res, res); + nsCOMPtr 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 piTarget = GetPIDOMEventTarget(); nsCOMPtr 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 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) { diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index f26fed5c9db..671537e1c16 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -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(); diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 1771672e508..812292ce97c 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -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; diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 1cccac8ce94..4b65baabccc 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -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); +}