Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "mozilla/HTMLEditor.h"
6 :
7 : #include "mozilla/Attributes.h"
8 : #include "mozilla/dom/Element.h"
9 : #include "mozilla/mozalloc.h"
10 : #include "nsAString.h"
11 : #include "nsCOMPtr.h"
12 : #include "nsComputedDOMStyle.h"
13 : #include "nsDebug.h"
14 : #include "nsError.h"
15 : #include "nsGkAtoms.h"
16 : #include "nsIAtom.h"
17 : #include "nsIContent.h"
18 : #include "nsID.h"
19 : #include "nsIDOMCSSPrimitiveValue.h"
20 : #include "nsIDOMCSSStyleDeclaration.h"
21 : #include "nsIDOMCSSValue.h"
22 : #include "nsIDOMElement.h"
23 : #include "nsIDOMEventTarget.h"
24 : #include "nsIDOMHTMLElement.h"
25 : #include "nsIDOMNode.h"
26 : #include "nsIDOMWindow.h"
27 : #include "nsIDocument.h"
28 : #include "nsIDocumentObserver.h"
29 : #include "nsIHTMLAbsPosEditor.h"
30 : #include "nsIHTMLInlineTableEditor.h"
31 : #include "nsIHTMLObjectResizer.h"
32 : #include "nsStubMutationObserver.h"
33 : #include "nsINode.h"
34 : #include "nsIPresShell.h"
35 : #include "nsISupportsImpl.h"
36 : #include "nsISupportsUtils.h"
37 : #include "nsLiteralString.h"
38 : #include "nsPresContext.h"
39 : #include "nsReadableUtils.h"
40 : #include "nsString.h"
41 : #include "nsStringFwd.h"
42 : #include "nsUnicharUtils.h"
43 : #include "nscore.h"
44 : #include "nsContentUtils.h" // for nsAutoScriptBlocker
45 :
46 : class nsIDOMEventListener;
47 : class nsISelection;
48 :
49 : namespace mozilla {
50 :
51 : using namespace dom;
52 :
53 : // retrieve an integer stored into a CSS computed float value
54 0 : static int32_t GetCSSFloatValue(nsIDOMCSSStyleDeclaration * aDecl,
55 : const nsAString & aProperty)
56 : {
57 0 : MOZ_ASSERT(aDecl);
58 :
59 0 : nsCOMPtr<nsIDOMCSSValue> value;
60 : // get the computed CSSValue of the property
61 0 : nsresult rv = aDecl->GetPropertyCSSValue(aProperty, getter_AddRefs(value));
62 0 : if (NS_FAILED(rv) || !value) {
63 0 : return 0;
64 : }
65 :
66 : // check the type of the returned CSSValue; we handle here only
67 : // pixel and enum types
68 0 : nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(value);
69 : uint16_t type;
70 0 : val->GetPrimitiveType(&type);
71 :
72 0 : float f = 0;
73 0 : switch (type) {
74 : case nsIDOMCSSPrimitiveValue::CSS_PX:
75 : // the value is in pixels, just get it
76 0 : rv = val->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, &f);
77 0 : NS_ENSURE_SUCCESS(rv, 0);
78 0 : break;
79 : case nsIDOMCSSPrimitiveValue::CSS_IDENT: {
80 : // the value is keyword, we have to map these keywords into
81 : // numeric values
82 0 : nsAutoString str;
83 0 : val->GetStringValue(str);
84 0 : if (str.EqualsLiteral("thin")) {
85 0 : f = 1;
86 0 : } else if (str.EqualsLiteral("medium")) {
87 0 : f = 3;
88 0 : } else if (str.EqualsLiteral("thick")) {
89 0 : f = 5;
90 : }
91 0 : break;
92 : }
93 : }
94 :
95 0 : return (int32_t) f;
96 : }
97 :
98 : class ElementDeletionObserver final : public nsStubMutationObserver
99 : {
100 : public:
101 0 : ElementDeletionObserver(nsIContent* aNativeAnonNode,
102 : nsIContent* aObservedNode)
103 0 : : mNativeAnonNode(aNativeAnonNode)
104 0 : , mObservedNode(aObservedNode)
105 0 : {}
106 :
107 : NS_DECL_ISUPPORTS
108 : NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
109 : NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
110 :
111 : protected:
112 0 : ~ElementDeletionObserver() {}
113 : nsIContent* mNativeAnonNode;
114 : nsIContent* mObservedNode;
115 : };
116 :
117 0 : NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
118 :
119 : void
120 0 : ElementDeletionObserver::ParentChainChanged(nsIContent* aContent)
121 : {
122 : // If the native anonymous content has been unbound already in
123 : // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
124 0 : if (aContent == mObservedNode && mNativeAnonNode &&
125 0 : mNativeAnonNode->GetParentNode() == aContent) {
126 : // If the observed node has been moved to another document, there isn't much
127 : // we can do easily. But at least be safe and unbind the native anonymous
128 : // content and stop observing changes.
129 0 : if (mNativeAnonNode->OwnerDoc() != mObservedNode->OwnerDoc()) {
130 0 : mObservedNode->RemoveMutationObserver(this);
131 0 : mObservedNode = nullptr;
132 0 : mNativeAnonNode->RemoveMutationObserver(this);
133 0 : mNativeAnonNode->UnbindFromTree();
134 0 : mNativeAnonNode = nullptr;
135 0 : NS_RELEASE_THIS();
136 0 : return;
137 : }
138 :
139 : // We're staying in the same document, just rebind the native anonymous
140 : // node so that the subtree root points to the right object etc.
141 0 : mNativeAnonNode->UnbindFromTree();
142 0 : mNativeAnonNode->BindToTree(mObservedNode->GetUncomposedDoc(), mObservedNode,
143 0 : mObservedNode, true);
144 : }
145 : }
146 :
147 : void
148 0 : ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode)
149 : {
150 0 : NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedNode,
151 : "Wrong aNode!");
152 0 : if (aNode == mNativeAnonNode) {
153 0 : mObservedNode->RemoveMutationObserver(this);
154 0 : mObservedNode = nullptr;
155 : } else {
156 0 : mNativeAnonNode->RemoveMutationObserver(this);
157 0 : mNativeAnonNode->UnbindFromTree();
158 0 : mNativeAnonNode = nullptr;
159 : }
160 :
161 0 : NS_RELEASE_THIS();
162 0 : }
163 :
164 : already_AddRefed<Element>
165 0 : HTMLEditor::CreateAnonymousElement(nsIAtom* aTag,
166 : nsIDOMNode* aParentNode,
167 : const nsAString& aAnonClass,
168 : bool aIsCreatedHidden)
169 : {
170 0 : if (NS_WARN_IF(!aParentNode)) {
171 0 : return nullptr;
172 : }
173 :
174 0 : nsCOMPtr<nsIContent> parentContent = do_QueryInterface(aParentNode);
175 0 : if (NS_WARN_IF(!parentContent)) {
176 0 : return nullptr;
177 : }
178 :
179 0 : nsCOMPtr<nsIDocument> doc = GetDocument();
180 0 : if (NS_WARN_IF(!doc)) {
181 0 : return nullptr;
182 : }
183 :
184 : // Get the pres shell
185 0 : nsCOMPtr<nsIPresShell> ps = GetPresShell();
186 0 : if (NS_WARN_IF(!ps)) {
187 0 : return nullptr;
188 : }
189 :
190 : // Create a new node through the element factory
191 0 : RefPtr<Element> newContent = CreateHTMLContent(aTag);
192 0 : if (NS_WARN_IF(!newContent)) {
193 0 : return nullptr;
194 : }
195 :
196 : // add the "hidden" class if needed
197 0 : if (aIsCreatedHidden) {
198 : nsresult rv =
199 0 : newContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
200 0 : NS_LITERAL_STRING("hidden"), true);
201 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
202 0 : return nullptr;
203 : }
204 : }
205 :
206 : // add an _moz_anonclass attribute if needed
207 0 : if (!aAnonClass.IsEmpty()) {
208 : nsresult rv =
209 0 : newContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_anonclass,
210 0 : aAnonClass, true);
211 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
212 0 : return nullptr;
213 : }
214 : }
215 :
216 : {
217 0 : nsAutoScriptBlocker scriptBlocker;
218 :
219 : // establish parenthood of the element
220 0 : newContent->SetIsNativeAnonymousRoot();
221 : nsresult rv =
222 0 : newContent->BindToTree(doc, parentContent, parentContent, true);
223 0 : if (NS_FAILED(rv)) {
224 0 : newContent->UnbindFromTree();
225 0 : return nullptr;
226 : }
227 : }
228 :
229 : // Record the NAC on the element, so that AllChildrenIterator can find it.
230 : auto nac = static_cast<ManualNAC*>(
231 0 : parentContent->GetProperty(nsGkAtoms::manualNACProperty));
232 0 : if (!nac) {
233 0 : nac = new ManualNAC();
234 0 : parentContent->SetProperty(nsGkAtoms::manualNACProperty, nac,
235 0 : nsINode::DeleteProperty<ManualNAC>);
236 : }
237 0 : nac->AppendElement(newContent);
238 :
239 : ElementDeletionObserver* observer =
240 0 : new ElementDeletionObserver(newContent, parentContent);
241 0 : NS_ADDREF(observer); // NodeWillBeDestroyed releases.
242 0 : parentContent->AddMutationObserver(observer);
243 0 : newContent->AddMutationObserver(observer);
244 :
245 : #ifdef DEBUG
246 : // Editor anonymous content gets passed to PostRecreateFramesFor... which
247 : // can't _really_ deal with anonymous content (because it can't get the frame
248 : // tree ordering right). But for us the ordering doesn't matter so this is
249 : // sort of ok.
250 0 : newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
251 0 : reinterpret_cast<void*>(true));
252 : #endif // DEBUG
253 :
254 : // display the element
255 0 : ps->PostRecreateFramesFor(newContent);
256 :
257 0 : return newContent.forget();
258 : }
259 :
260 : // Removes event listener and calls DeleteRefToAnonymousNode.
261 : void
262 0 : HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
263 : nsIDOMEventListener* aListener,
264 : bool aUseCapture,
265 : Element* aElement,
266 : nsIPresShell* aShell)
267 : {
268 0 : nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
269 0 : if (evtTarget) {
270 0 : evtTarget->RemoveEventListener(aEvent, aListener, aUseCapture);
271 : }
272 0 : DeleteRefToAnonymousNode(aElement, aShell);
273 0 : }
274 :
275 : // Deletes all references to an anonymous element
276 : void
277 0 : HTMLEditor::DeleteRefToAnonymousNode(nsIContent* aContent,
278 : nsIPresShell* aShell)
279 : {
280 : // call ContentRemoved() for the anonymous content
281 : // node so its references get removed from the frame manager's
282 : // undisplay map, and its layout frames get destroyed!
283 :
284 0 : if (NS_WARN_IF(!aContent)) {
285 0 : return;
286 : }
287 :
288 0 : nsIContent* parentContent = aContent->GetParent();
289 0 : if (NS_WARN_IF(!parentContent)) {
290 : // aContent was already removed?
291 0 : return;
292 : }
293 :
294 0 : nsAutoScriptBlocker scriptBlocker;
295 : // Need to check whether aShell has been destroyed (but not yet deleted).
296 : // In that case presContext->GetPresShell() returns nullptr.
297 : // See bug 338129.
298 0 : if (aContent->IsInComposedDoc() && aShell && aShell->GetPresContext() &&
299 0 : aShell->GetPresContext()->GetPresShell() == aShell) {
300 0 : nsCOMPtr<nsIDocumentObserver> docObserver = do_QueryInterface(aShell);
301 0 : if (docObserver) {
302 : // Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
303 : // knows we're messing with the frame tree.
304 0 : nsCOMPtr<nsIDocument> document = GetDocument();
305 0 : if (document) {
306 0 : docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
307 : }
308 :
309 : // XXX This is wrong (bug 439258). Once it's fixed, the NS_WARNING
310 : // in RestyleManager::RestyleForRemove should be changed back
311 : // to an assertion.
312 0 : docObserver->ContentRemoved(aContent->GetComposedDoc(),
313 : parentContent, aContent, -1,
314 0 : aContent->GetPreviousSibling());
315 0 : if (document) {
316 0 : docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
317 : }
318 : }
319 : }
320 :
321 : // Remove reference from the parent element.
322 : auto nac = static_cast<mozilla::ManualNAC*>(
323 0 : parentContent->GetProperty(nsGkAtoms::manualNACProperty));
324 0 : MOZ_ASSERT(nac);
325 0 : nac->RemoveElement(aContent);
326 0 : if (nac->IsEmpty()) {
327 0 : parentContent->DeleteProperty(nsGkAtoms::manualNACProperty);
328 : }
329 :
330 0 : aContent->UnbindFromTree();
331 : }
332 :
333 : // The following method is mostly called by a selection listener. When a
334 : // selection change is notified, the method is called to check if resizing
335 : // handles, a grabber and/or inline table editing UI need to be displayed
336 : // or refreshed
337 : NS_IMETHODIMP
338 0 : HTMLEditor::CheckSelectionStateForAnonymousButtons(nsISelection* aSelection)
339 : {
340 0 : NS_ENSURE_ARG_POINTER(aSelection);
341 :
342 : // early way out if all contextual UI extensions are disabled
343 0 : NS_ENSURE_TRUE(mIsObjectResizingEnabled ||
344 : mIsAbsolutelyPositioningEnabled ||
345 : mIsInlineTableEditingEnabled, NS_OK);
346 :
347 : // Don't change selection state if we're moving.
348 0 : if (mIsMoving) {
349 0 : return NS_OK;
350 : }
351 :
352 0 : nsCOMPtr<nsIDOMElement> focusElement;
353 : // let's get the containing element of the selection
354 0 : nsresult rv = GetSelectionContainer(getter_AddRefs(focusElement));
355 0 : NS_ENSURE_TRUE(focusElement, NS_OK);
356 0 : NS_ENSURE_SUCCESS(rv, rv);
357 :
358 : // If we're not in a document, don't try to add resizers
359 0 : nsCOMPtr<dom::Element> focusElementNode = do_QueryInterface(focusElement);
360 0 : NS_ENSURE_STATE(focusElementNode);
361 0 : if (!focusElementNode->IsInUncomposedDoc()) {
362 0 : return NS_OK;
363 : }
364 :
365 : // what's its tag?
366 0 : nsAutoString focusTagName;
367 0 : rv = focusElement->GetTagName(focusTagName);
368 0 : NS_ENSURE_SUCCESS(rv, rv);
369 0 : ToLowerCase(focusTagName);
370 0 : nsCOMPtr<nsIAtom> focusTagAtom = NS_Atomize(focusTagName);
371 :
372 0 : nsCOMPtr<nsIDOMElement> absPosElement;
373 0 : if (mIsAbsolutelyPositioningEnabled) {
374 : // Absolute Positioning support is enabled, is the selection contained
375 : // in an absolutely positioned element ?
376 : rv =
377 0 : GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(absPosElement));
378 0 : NS_ENSURE_SUCCESS(rv, rv);
379 : }
380 :
381 0 : nsCOMPtr<nsIDOMElement> cellElement;
382 0 : if (mIsObjectResizingEnabled || mIsInlineTableEditingEnabled) {
383 : // Resizing or Inline Table Editing is enabled, we need to check if the
384 : // selection is contained in a table cell
385 0 : rv = GetElementOrParentByTagName(NS_LITERAL_STRING("td"),
386 : nullptr,
387 0 : getter_AddRefs(cellElement));
388 0 : NS_ENSURE_SUCCESS(rv, rv);
389 : }
390 :
391 0 : if (mIsObjectResizingEnabled && cellElement) {
392 : // we are here because Resizing is enabled AND selection is contained in
393 : // a cell
394 :
395 : // get the enclosing table
396 0 : if (nsGkAtoms::img != focusTagAtom) {
397 : // the element container of the selection is not an image, so we'll show
398 : // the resizers around the table
399 0 : nsCOMPtr<nsIDOMNode> tableNode = GetEnclosingTable(cellElement);
400 0 : focusElement = do_QueryInterface(tableNode);
401 0 : focusTagAtom = nsGkAtoms::table;
402 : }
403 : }
404 :
405 : // we allow resizers only around images, tables, and absolutely positioned
406 : // elements. If we don't have image/table, let's look at the latter case.
407 0 : if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
408 0 : focusElement = absPosElement;
409 : }
410 :
411 : // at this point, focusElement contains the element for Resizing,
412 : // cellElement contains the element for InlineTableEditing
413 : // absPosElement contains the element for Positioning
414 :
415 : // Note: All the Hide/Show methods below may change attributes on real
416 : // content which means a DOMAttrModified handler may cause arbitrary
417 : // side effects while this code runs (bug 420439).
418 :
419 0 : if (mIsAbsolutelyPositioningEnabled && mAbsolutelyPositionedObject &&
420 0 : absPosElement != GetAsDOMNode(mAbsolutelyPositionedObject)) {
421 0 : rv = HideGrabber();
422 0 : NS_ENSURE_SUCCESS(rv, rv);
423 0 : NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
424 : }
425 :
426 0 : if (mIsObjectResizingEnabled && mResizedObject &&
427 0 : GetAsDOMNode(mResizedObject) != focusElement) {
428 0 : rv = HideResizers();
429 0 : NS_ENSURE_SUCCESS(rv, rv);
430 0 : NS_ASSERTION(!mResizedObject, "HideResizers failed");
431 : }
432 :
433 0 : if (mIsInlineTableEditingEnabled && mInlineEditedCell &&
434 0 : mInlineEditedCell != cellElement) {
435 0 : rv = HideInlineTableEditingUI();
436 0 : NS_ENSURE_SUCCESS(rv, rv);
437 0 : NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
438 : }
439 :
440 : // now, let's display all contextual UI for good
441 0 : nsIContent* hostContent = GetActiveEditingHost();
442 0 : nsCOMPtr<nsIDOMNode> hostNode = do_QueryInterface(hostContent);
443 :
444 0 : if (mIsObjectResizingEnabled && focusElement &&
445 0 : IsModifiableNode(focusElement) && focusElement != hostNode) {
446 0 : if (nsGkAtoms::img == focusTagAtom) {
447 0 : mResizedObjectIsAnImage = true;
448 : }
449 0 : if (mResizedObject) {
450 0 : nsresult rv = RefreshResizers();
451 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
452 0 : return rv;
453 : }
454 : } else {
455 0 : nsresult rv = ShowResizers(focusElement);
456 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
457 0 : return rv;
458 : }
459 : }
460 : }
461 :
462 0 : if (mIsAbsolutelyPositioningEnabled && absPosElement &&
463 0 : IsModifiableNode(absPosElement) && absPosElement != hostNode) {
464 0 : if (mAbsolutelyPositionedObject) {
465 0 : nsresult rv = RefreshGrabber();
466 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
467 0 : return rv;
468 : }
469 : } else {
470 0 : nsresult rv = ShowGrabberOnElement(absPosElement);
471 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
472 0 : return rv;
473 : }
474 : }
475 : }
476 :
477 0 : if (mIsInlineTableEditingEnabled && cellElement &&
478 0 : IsModifiableNode(cellElement) && cellElement != hostNode) {
479 0 : if (mInlineEditedCell) {
480 0 : nsresult rv = RefreshInlineTableEditingUI();
481 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
482 0 : return rv;
483 : }
484 : } else {
485 0 : nsresult rv = ShowInlineTableEditingUI(cellElement);
486 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
487 0 : return rv;
488 : }
489 : }
490 : }
491 :
492 0 : return NS_OK;
493 : }
494 :
495 : // Resizing and Absolute Positioning need to know everything about the
496 : // containing box of the element: position, size, margins, borders
497 : nsresult
498 0 : HTMLEditor::GetPositionAndDimensions(nsIDOMElement* aElement,
499 : int32_t& aX,
500 : int32_t& aY,
501 : int32_t& aW,
502 : int32_t& aH,
503 : int32_t& aBorderLeft,
504 : int32_t& aBorderTop,
505 : int32_t& aMarginLeft,
506 : int32_t& aMarginTop)
507 : {
508 0 : nsCOMPtr<Element> element = do_QueryInterface(aElement);
509 0 : NS_ENSURE_ARG_POINTER(element);
510 :
511 : // Is the element positioned ? let's check the cheap way first...
512 0 : bool isPositioned = false;
513 : nsresult rv =
514 0 : aElement->HasAttribute(NS_LITERAL_STRING("_moz_abspos"), &isPositioned);
515 0 : NS_ENSURE_SUCCESS(rv, rv);
516 0 : if (!isPositioned) {
517 : // hmmm... the expensive way now...
518 0 : nsAutoString positionStr;
519 0 : mCSSEditUtils->GetComputedProperty(*element, *nsGkAtoms::position,
520 0 : positionStr);
521 0 : isPositioned = positionStr.EqualsLiteral("absolute");
522 : }
523 :
524 0 : if (isPositioned) {
525 : // Yes, it is absolutely positioned
526 0 : mResizedObjectIsAbsolutelyPositioned = true;
527 :
528 : // Get the all the computed css styles attached to the element node
529 : RefPtr<nsComputedDOMStyle> cssDecl =
530 0 : mCSSEditUtils->GetComputedStyle(element);
531 0 : NS_ENSURE_STATE(cssDecl);
532 :
533 0 : aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
534 0 : aBorderTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
535 0 : aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
536 0 : aMarginTop = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
537 :
538 0 : aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) +
539 0 : aMarginLeft + aBorderLeft;
540 0 : aY = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("top")) +
541 0 : aMarginTop + aBorderTop;
542 0 : aW = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("width"));
543 0 : aH = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("height"));
544 : } else {
545 0 : mResizedObjectIsAbsolutelyPositioned = false;
546 0 : nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aElement);
547 0 : if (!htmlElement) {
548 0 : return NS_ERROR_NULL_POINTER;
549 : }
550 0 : GetElementOrigin(aElement, aX, aY);
551 :
552 0 : if (NS_WARN_IF(NS_FAILED(htmlElement->GetOffsetWidth(&aW))) ||
553 0 : NS_WARN_IF(NS_FAILED(htmlElement->GetOffsetHeight(&aH)))) {
554 0 : return rv;
555 : }
556 :
557 0 : aBorderLeft = 0;
558 0 : aBorderTop = 0;
559 0 : aMarginLeft = 0;
560 0 : aMarginTop = 0;
561 : }
562 0 : return NS_OK;
563 : }
564 :
565 : // self-explanatory
566 : void
567 0 : HTMLEditor::SetAnonymousElementPosition(int32_t aX,
568 : int32_t aY,
569 : Element* aElement)
570 : {
571 0 : mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::left, aX);
572 0 : mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::top, aY);
573 0 : }
574 :
575 : } // namespace mozilla
|