Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/editor/libeditor/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 34 kB image not shown  

Quelle  HTMLAbsPositionEditor.cpp   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "HTMLEditor.h"

#include <math.h>

#include "CSSEditUtils.h"
#include "EditAction.h"
#include "EditorLineBreak.h"
#include "HTMLEditHelpers.h"
#include "HTMLEditorEventListener.h"
#include "HTMLEditUtils.h"

#include "mozilla/EventListenerManager.h"
#include "mozilla/mozalloc.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs_editor.h"
#include "mozilla/dom/AncestorIterator.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EventTarget.h"
#include "nsAString.h"
#include "nsCOMPtr.h"
#include "nsComputedDOMStyle.h"
#include "nsDebug.h"
#include "nsError.h"
#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsROCSSPrimitiveValue.h"
#include "nsINode.h"
#include "nsIPrincipal.h"
#include "nsISupportsImpl.h"
#include "nsISupportsUtils.h"
#include "nsLiteralString.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsStringFwd.h"
#include "nsStyledElement.h"
#include "nscore.h"
#include <algorithm>

namespace mozilla {

using namespace dom;

nsresult HTMLEditor::SetSelectionToAbsoluteOrStaticAsAction(
    bool aEnabled, nsIPrincipal* aPrincipal) {
  AutoEditActionDataSetter editActionData(
      *this, EditAction::eSetPositionToAbsoluteOrStatic, aPrincipal);
  nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
  if (NS_FAILED(rv)) {
    NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
                         "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    return rv;
  }

  const RefPtr<Element> editingHost = ComputeEditingHost();
  if (!editingHost) {
    return NS_SUCCESS_DOM_NO_OPERATION;
  }

  if (aEnabled) {
    Result<EditActionResult, nsresult> result =
        SetSelectionToAbsoluteAsSubAction(*editingHost);
    if (MOZ_UNLIKELY(result.isErr())) {
      NS_WARNING("HTMLEditor::SetSelectionToAbsoluteAsSubAction() failed");
      return result.unwrapErr();
    }
    return NS_OK;
  }
  Result<EditActionResult, nsresult> result = SetSelectionToStaticAsSubAction();
  if (MOZ_UNLIKELY(result.isErr())) {
    NS_WARNING("HTMLEditor::SetSelectionToStaticAsSubAction() failed");
    return result.unwrapErr();
  }
  return NS_OK;
}

already_AddRefed<Element>
HTMLEditor::GetAbsolutelyPositionedSelectionContainer() const {
  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
  if (NS_WARN_IF(!editActionData.CanHandle())) {
    return nullptr;
  }

  Element* selectionContainerElement = GetSelectionContainerElement();
  if (NS_WARN_IF(!selectionContainerElement)) {
    return nullptr;
  }

  AutoTArray<RefPtr<Element>, 24> arrayOfParentElements;
  for (Element* element :
       selectionContainerElement->InclusiveAncestorsOfType<Element>()) {
    arrayOfParentElements.AppendElement(element);
  }

  nsAutoString positionValue;
  for (RefPtr<Element> element = selectionContainerElement; element;
       element = element->GetParentElement()) {
    if (element->IsHTMLElement(nsGkAtoms::html)) {
      NS_WARNING(
          "HTMLEditor::GetAbsolutelyPositionedSelectionContainer() reached "
          " element");
      return nullptr;
    }
    nsCOMPtr<nsINode> parentNode = element->GetParentNode();
    nsresult rv = CSSEditUtils::GetComputedProperty(
        MOZ_KnownLive(*element), *nsGkAtoms::position, positionValue);
    if (NS_FAILED(rv)) {
      NS_WARNING(
          "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) failed");
      return nullptr;
    }
    if (NS_WARN_IF(Destroyed()) ||
        NS_WARN_IF(parentNode != element->GetParentNode())) {
      return nullptr;
    }
    if (positionValue.EqualsLiteral("absolute")) {
      return element.forget();
    }
  }
  return nullptr;
}

NS_IMETHODIMP HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled) {
  *aIsEnabled = IsAbsolutePositionEditorEnabled();
  return NS_OK;
}

NS_IMETHODIMP HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) {
  EnableAbsolutePositionEditor(aIsEnabled);
  return NS_OK;
}

NS_IMETHODIMP HTMLEditor::GetIsAbsolutePositioningActive(bool* aIsActive) {
  MOZ_ASSERT(aIsActive);
  *aIsActive = !!mAbsolutelyPositionedObject;
  return NS_OK;
}

Result<int32_t, nsresult> HTMLEditor::AddZIndexWithTransaction(
    nsStyledElement& aStyledElement, int32_t aChange) {
  if (!aChange) {
    return 0;  // XXX Why don't we return current z-index value in this case?
  }

  int32_t zIndex = GetZIndex(aStyledElement);
  if (NS_WARN_IF(Destroyed())) {
    return Err(NS_ERROR_EDITOR_DESTROYED);
  }
  zIndex = std::max(zIndex + aChange, 0);
  nsresult rv = SetZIndexWithTransaction(aStyledElement, zIndex);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING("HTMLEditor::SetZIndexWithTransaction() destroyed the editor");
    return Err(NS_ERROR_EDITOR_DESTROYED);
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "HTMLEditor::SetZIndexWithTransaction() failed, but ignored");
  return zIndex;
}

nsresult HTMLEditor::SetZIndexWithTransaction(nsStyledElement& aStyledElement,
                                              int32_t aZIndex) {
  nsAutoString zIndexValue;
  zIndexValue.AppendInt(aZIndex);

  nsresult rv = CSSEditUtils::SetCSSPropertyWithTransaction(
      *this, aStyledElement, *nsGkAtoms::z_index, zIndexValue);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::z_index) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::"
                       "z_index) failed, but ignored");
  return NS_OK;
}

nsresult HTMLEditor::AddZIndexAsAction(int32_t aChange,
                                       nsIPrincipal* aPrincipal) {
  MOZ_ASSERT(IsEditActionDataAvailable());

  AutoEditActionDataSetter editActionData(
      *this, EditAction::eIncreaseOrDecreaseZIndex, aPrincipal);
  nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
  if (NS_FAILED(rv)) {
    NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
                         "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    return EditorBase::ToGenericNSResult(rv);
  }

  Result<EditActionResult, nsresult> result = AddZIndexAsSubAction(aChange);
  if (MOZ_UNLIKELY(result.isErr())) {
    NS_WARNING("HTMLEditor::AddZIndexAsSubAction() failed");
    return EditorBase::ToGenericNSResult(result.unwrapErr());
  }
  return NS_OK;
}

int32_t HTMLEditor::GetZIndex(Element& aElement) {
  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
  if (NS_WARN_IF(!editActionData.CanHandle())) {
    return 0;
  }

  nsAutoString zIndexValue;

  nsresult rv = CSSEditUtils::GetSpecifiedProperty(
      aElement, *nsGkAtoms::z_index, zIndexValue);
  if (NS_FAILED(rv)) {
    NS_WARNING("CSSEditUtils::GetSpecifiedProperty(nsGkAtoms::z_index) failed");
    return 0;
  }
  if (zIndexValue.EqualsLiteral("auto")) {
    if (!aElement.GetParentElement()) {
      NS_WARNING("aElement was an orphan node or the root node");
      return 0;
    }
    // we have to look at the positioned ancestors
    // cf. CSS 2 spec section 9.9.1
    nsAutoString positionValue;
    for (RefPtr<Element> element = aElement.GetParentElement(); element;
         element = element->GetParentElement()) {
      if (element->IsHTMLElement(nsGkAtoms::body)) {
        return 0;
      }
      nsCOMPtr<nsINode> parentNode = element->GetParentElement();
      nsresult rv = CSSEditUtils::GetComputedProperty(
          *element, *nsGkAtoms::position, positionValue);
      if (NS_FAILED(rv)) {
        NS_WARNING(
            "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) failed");
        return 0;
      }
      if (NS_WARN_IF(Destroyed()) ||
          NS_WARN_IF(parentNode != element->GetParentNode())) {
        return 0;
      }
      if (!positionValue.EqualsLiteral("absolute")) {
        continue;
      }
      // ah, we found one, what's its z-index ? If its z-index is auto,
      // we have to continue climbing the document's tree
      rv = CSSEditUtils::GetComputedProperty(*element, *nsGkAtoms::z_index,
                                             zIndexValue);
      if (NS_FAILED(rv)) {
        NS_WARNING(
            "CSSEditUtils::GetComputedProperty(nsGkAtoms::z_index) failed");
        return 0;
      }
      if (NS_WARN_IF(Destroyed()) ||
          NS_WARN_IF(parentNode != element->GetParentNode())) {
        return 0;
      }
      if (!zIndexValue.EqualsLiteral("auto")) {
        break;
      }
    }
  }

  if (zIndexValue.EqualsLiteral("auto")) {
    return 0;
  }

  nsresult rvIgnored;
  int32_t result = zIndexValue.ToInteger(&rvIgnored);
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                       "nsAString::ToInteger() failed, but ignored");
  return result;
}

bool HTMLEditor::CreateGrabberInternal(nsIContent& aParentContent) {
  if (NS_WARN_IF(mGrabber)) {
    return false;
  }

  mGrabber = CreateAnonymousElement(nsGkAtoms::span, aParentContent,
                                    u"mozGrabber"_ns, false);

  // mGrabber may be destroyed during creation due to there may be
  // mutation event listener.
  if (!mGrabber) {
    NS_WARNING(
        "HTMLEditor::CreateAnonymousElement(nsGkAtoms::span, mozGrabber) "
        "failed");
    return false;
  }

  EventListenerManager* eventListenerManager =
      mGrabber->GetOrCreateListenerManager();
  eventListenerManager->AddEventListenerByType(
      mEventListener, u"mousedown"_ns, TrustedEventsAtSystemGroupBubble());
  MOZ_ASSERT(mGrabber);
  return true;
}

nsresult HTMLEditor::RefreshGrabberInternal() {
  MOZ_ASSERT(IsEditActionDataAvailable());

  if (!mAbsolutelyPositionedObject) {
    return NS_OK;
  }

  OwningNonNull<Element> absolutelyPositionedObject =
      *mAbsolutelyPositionedObject;
  nsresult rv = GetPositionAndDimensions(
      absolutelyPositionedObject, mPositionedObjectX, mPositionedObjectY,
      mPositionedObjectWidth, mPositionedObjectHeight,
      mPositionedObjectBorderLeft, mPositionedObjectBorderTop,
      mPositionedObjectMarginLeft, mPositionedObjectMarginTop);
  if (NS_FAILED(rv)) {
    NS_WARNING("HTMLEditor::GetPositionAndDimensions() failed");
    return rv;
  }
  if (NS_WARN_IF(absolutelyPositionedObject != mAbsolutelyPositionedObject)) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<nsStyledElement> grabberStyledElement =
      nsStyledElement::FromNodeOrNull(mGrabber.get());
  if (!grabberStyledElement) {
    return NS_OK;
  }
  rv = SetAnonymousElementPositionWithoutTransaction(
      *grabberStyledElement, mPositionedObjectX + 12, mPositionedObjectY - 14);
  if (NS_WARN_IF(Destroyed())) {
    return NS_ERROR_EDITOR_DESTROYED;
  }
  if (NS_FAILED(rv)) {
    NS_WARNING(
        "HTMLEditor::SetAnonymousElementPositionWithoutTransaction() failed");
    return rv;
  }
  if (NS_WARN_IF(grabberStyledElement != mGrabber.get())) {
    return NS_ERROR_FAILURE;
  }
  return NS_OK;
}

void HTMLEditor::HideGrabberInternal() {
  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    return;
  }

  // Move all members to the local variables first since mutation event
  // listener may try to show grabber while we're hiding them.
  RefPtr<Element> absolutePositioningObject =
      std::move(mAbsolutelyPositionedObject);
  ManualNACPtr grabber = std::move(mGrabber);
  ManualNACPtr positioningShadow = std::move(mPositioningShadow);

  // If we're still in dragging mode, it means that the dragging is canceled
  // by the web app.
  if (mGrabberClicked || mIsMoving) {
    mGrabberClicked = false;
    mIsMoving = false;
    if (mEventListener) {
      DebugOnly<nsresult> rvIgnored =
          static_cast<HTMLEditorEventListener*>(mEventListener.get())
              ->ListenToMouseMoveEventForGrabber(false);
      NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                           "HTMLEditorEventListener::"
                           "ListenToMouseMoveEventForGrabber(false) failed");
    }
  }

  DebugOnly<nsresult> rv = absolutePositioningObject->UnsetAttr(
      kNameSpaceID_None, nsGkAtoms::_moz_abspos, true);
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "Element::UnsetAttr(nsGkAtoms::_moz_abspos) failed, but ignored");

  // We allow the pres shell to be null; when it is, we presume there
  // are no document observers to notify, but we still want to
  // UnbindFromTree.
  RefPtr<PresShell> presShell = GetPresShell();
  if (grabber) {
    DeleteRefToAnonymousNode(std::move(grabber), presShell);
  }
  if (positioningShadow) {
    DeleteRefToAnonymousNode(std::move(positioningShadow), presShell);
  }
}

nsresult HTMLEditor::ShowGrabberInternal(Element& aElement) {
  MOZ_ASSERT(IsEditActionDataAvailable());

  const RefPtr<Element> editingHost = ComputeEditingHost();
  if (NS_WARN_IF(!editingHost) ||
      NS_WARN_IF(!aElement.IsInclusiveDescendantOf(editingHost))) {
    return NS_ERROR_UNEXPECTED;
  }

  if (NS_WARN_IF(mGrabber)) {
    return NS_ERROR_UNEXPECTED;
  }

  nsAutoString classValue;
  nsresult rv =
      GetTemporaryStyleForFocusedPositionedElement(aElement, classValue);
  if (NS_FAILED(rv)) {
    NS_WARNING(
        "HTMLEditor::GetTemporaryStyleForFocusedPositionedElement() failed");
    return rv;
  }

  rv = aElement.SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos, classValue,
                        true);
  if (NS_FAILED(rv)) {
    NS_WARNING("Element::SetAttr(nsGkAtoms::_moz_abspos) failed");
    return rv;
  }

  mAbsolutelyPositionedObject = &aElement;

  Element* parentElement = aElement.GetParentElement();
  if (NS_WARN_IF(!parentElement)) {
    return NS_ERROR_FAILURE;
  }

  if (!CreateGrabberInternal(*parentElement)) {
    NS_WARNING("HTMLEditor::CreateGrabberInternal() failed");
    return NS_ERROR_FAILURE;
  }

  // If we succeeded to create the grabber, HideGrabberInternal() hasn't been
  // called yet.  So, mAbsolutelyPositionedObject should be non-nullptr.
  MOZ_ASSERT(mAbsolutelyPositionedObject);

  // Finally, move the grabber to proper position.
  rv = RefreshGrabberInternal();
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "HTMLEditor::RefereshGrabberInternal() failed");
  return rv;
}

nsresult HTMLEditor::StartMoving() {
  MOZ_ASSERT(mGrabber);

  RefPtr<Element> parentElement = mGrabber->GetParentElement();
  if (NS_WARN_IF(!parentElement) || NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    return NS_ERROR_FAILURE;
  }

  // now, let's create the resizing shadow
  mPositioningShadow =
      CreateShadow(*parentElement, *mAbsolutelyPositionedObject);
  if (!mPositioningShadow) {
    NS_WARNING("HTMLEditor::CreateShadow() failed");
    return NS_ERROR_FAILURE;
  }
  if (!mAbsolutelyPositionedObject) {
    NS_WARNING("The target has gone during HTMLEditor::CreateShadow()");
    return NS_ERROR_FAILURE;
  }
  RefPtr<Element> positioningShadow = mPositioningShadow.get();
  RefPtr<Element> absolutelyPositionedObject = mAbsolutelyPositionedObject;
  nsresult rv =
      SetShadowPosition(*positioningShadow, *absolutelyPositionedObject,
                        mPositionedObjectX, mPositionedObjectY);
  if (NS_FAILED(rv)) {
    NS_WARNING("HTMLEditor::SetShadowPosition() failed");
    return rv;
  }

  // make the shadow appear
  DebugOnly<nsresult> rvIgnored =
      mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_classtrue);
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rvIgnored),
      "Element::UnsetAttr(nsGkAtoms::_class) failed, but ignored");

  // position it
  if (RefPtr<nsStyledElement> positioningShadowStyledElement =
          nsStyledElement::FromNode(mPositioningShadow.get())) {
    nsresult rv;
    rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
        *positioningShadowStyledElement, *nsGkAtoms::width,
        mPositionedObjectWidth);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
          "nsGkAtoms::width) destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                         "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
                         "nsGkAtoms::width) failed, but ignored");
    rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
        *positioningShadowStyledElement, *nsGkAtoms::height,
        mPositionedObjectHeight);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
          "nsGkAtoms::height) destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                         "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
                         "nsGkAtoms::height) failed, but ignored");
  }

  mIsMoving = true;
  return NS_OK;  // XXX Looks like nobody refers this result
}

void HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY) const {
  if (mSnapToGridEnabled && mGridSize) {
    newX = (int32_t)floor(((float)newX / (float)mGridSize) + 0.5f) * mGridSize;
    newY = (int32_t)floor(((float)newY / (float)mGridSize) + 0.5f) * mGridSize;
  }
}

nsresult HTMLEditor::GrabberClicked() {
  if (NS_WARN_IF(!mEventListener)) {
    return NS_ERROR_NOT_INITIALIZED;
  }
  nsresult rv = static_cast<HTMLEditorEventListener*>(mEventListener.get())
                    ->ListenToMouseMoveEventForGrabber(true);
  if (NS_FAILED(rv)) {
    NS_WARNING(
        "HTMLEditorEventListener::ListenToMouseMoveEventForGrabber(true) "
        "failed, but ignored");
    return NS_OK;
  }
  mGrabberClicked = true;
  return NS_OK;
}

nsresult HTMLEditor::EndMoving() {
  if (mPositioningShadow) {
    RefPtr<PresShell> presShell = GetPresShell();
    if (NS_WARN_IF(!presShell)) {
      return NS_ERROR_NOT_INITIALIZED;
    }

    DeleteRefToAnonymousNode(std::move(mPositioningShadow), presShell);

    mPositioningShadow = nullptr;
  }

  if (mEventListener) {
    DebugOnly<nsresult> rvIgnored =
        static_cast<HTMLEditorEventListener*>(mEventListener.get())
            ->ListenToMouseMoveEventForGrabber(false);
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                         "HTMLEditorEventListener::"
                         "ListenToMouseMoveEventForGrabber(false) failed");
  }

  mGrabberClicked = false;
  mIsMoving = false;
  nsresult rv = RefreshEditingUI();
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "HTMLEditor::RefreshEditingUI() failed");
  return rv;
}

nsresult HTMLEditor::SetFinalPosition(int32_t aX, int32_t aY) {
  MOZ_ASSERT(IsEditActionDataAvailable());

  nsresult rv = EndMoving();
  if (NS_FAILED(rv)) {
    NS_WARNING("HTMLEditor::EndMoving() failed");
    return rv;
  }

  // we have now to set the new width and height of the resized object
  // we don't set the x and y position because we don't control that in
  // a normal HTML layout
  int32_t newX = mPositionedObjectX + aX - mOriginalX -
                 (mPositionedObjectBorderLeft + mPositionedObjectMarginLeft);
  int32_t newY = mPositionedObjectY + aY - mOriginalY -
                 (mPositionedObjectBorderTop + mPositionedObjectMarginTop);

  SnapToGrid(newX, newY);

  nsAutoString x, y;
  x.AppendInt(newX);
  y.AppendInt(newY);

  // we want one transaction only from a user's point of view
  AutoPlaceholderBatch treatAsOneTransaction(
      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);

  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    return NS_ERROR_FAILURE;
  }
  if (RefPtr<nsStyledElement> styledAbsolutelyPositionedElement =
          nsStyledElement::FromNode(mAbsolutelyPositionedObject)) {
    nsresult rv;
    rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(
        *this, *styledAbsolutelyPositionedElement, *nsGkAtoms::top, newY);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
          "destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(
        NS_SUCCEEDED(rv),
        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
        "failed, but ignored");
    rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(
        *this, *styledAbsolutelyPositionedElement, *nsGkAtoms::left, newX);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
          "destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(
        NS_SUCCEEDED(rv),
        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
        "failed, but ignored");
  }
  // keep track of that size
  mPositionedObjectX = newX;
  mPositionedObjectY = newY;

  rv = RefreshResizersInternal();
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "HTMLEditor::RefreshResizersInternal() failed");
  return rv;
}

nsresult HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
                                                   bool aEnabled) {
  nsAutoString positionValue;
  DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
      aElement, *nsGkAtoms::position, positionValue);
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                       "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) "
                       "failed, but ignored");
  // nothing to do if the element is already in the state we want
  if (positionValue.EqualsLiteral("absolute") == aEnabled) {
    return NS_OK;
  }

  if (aEnabled) {
    nsresult rv = SetPositionToAbsolute(aElement);
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                         "HTMLEditor::SetPositionToAbsolute() failed");
    return rv;
  }

  nsresult rv = SetPositionToStatic(aElement);
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "HTMLEditor::SetPositionToStatic() failed");
  return rv;
}

nsresult HTMLEditor::SetPositionToAbsolute(Element& aElement) {
  MOZ_ASSERT(IsEditActionDataAvailable());

  AutoPlaceholderBatch treatAsOneTransaction(
      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);

  int32_t x, y;
  DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, x, y);
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
                       "HTMLEditor::GetElementOrigin() failed, but ignored");

  nsStyledElement* styledElement = nsStyledElement::FromNode(&aElement);
  if (styledElement) {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    nsresult rv = CSSEditUtils::SetCSSPropertyWithTransaction(
        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::position,
        u"absolute"_ns);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::SetCSSProperyWithTransaction(nsGkAtoms::Position) "
          "destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(
        NS_SUCCEEDED(rvIgnored),
        "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::position, "
        "absolute) failed, but ignored");
  }

  SnapToGrid(x, y);
  if (styledElement) {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    nsresult rv =
        SetTopAndLeftWithTransaction(MOZ_KnownLive(*styledElement), x, y);
    if (NS_FAILED(rv)) {
      NS_WARNING("HTMLEditor::SetTopAndLeftWithTransaction() failed");
      return rv;
    }
  }

  // we may need to create a br if the positioned element is alone in its
  // container
  nsINode* parentNode = aElement.GetParentNode();
  if (parentNode->GetChildCount() != 1) {
    return NS_OK;
  }
  Result<CreateLineBreakResult, nsresult> insertBRElementResultOrError =
      InsertLineBreak(WithTransaction::Yes, LineBreakType::BRElement,
                      EditorDOMPoint(parentNode, 0u));
  if (MOZ_UNLIKELY(insertBRElementResultOrError.isErr())) {
    NS_WARNING(
        "HTMLEditor::InsertLineBreak(WithTransaction::Yes, "
        "LineBreakType::BRElement) failed");
    return insertBRElementResultOrError.unwrapErr();
  }
  CreateLineBreakResult insertBRElementResult =
      insertBRElementResultOrError.unwrap();
  MOZ_ASSERT(insertBRElementResult.Handled());
  // XXX Is this intentional selection change?
  nsresult rv = insertBRElementResult.SuggestCaretPointTo(
      *this, {SuggestCaret::OnlyIfHasSuggestion,
              SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "CreateElementResult::SuggestCaretPointTo() failed");
  return rv;
}

nsresult HTMLEditor::SetPositionToStatic(Element& aElement) {
  nsStyledElement* styledElement = nsStyledElement::FromNode(&aElement);
  if (NS_WARN_IF(!styledElement)) {
    return NS_ERROR_INVALID_ARG;
  }

  AutoPlaceholderBatch treatAsOneTransaction(
      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);

  nsresult rv;
  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::position, u""_ns);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::position) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::position) "
      "failed, but ignored");
  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::top, u""_ns);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::top) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::top) "
      "failed, but ignored");
  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::left, u""_ns);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::left) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::left) "
      "failed, but ignored");
  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::z_index, u""_ns);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::z_index) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::z_index) "
      "failed, but ignored");

  if (!HTMLEditUtils::IsImage(styledElement)) {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::width, u""_ns);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::width) "
          "destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(
        NS_SUCCEEDED(rv),
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::width) "
        "failed, but ignored");
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::height, u""_ns);
    if (rv == NS_ERROR_EDITOR_DESTROYED) {
      NS_WARNING(
          "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::height) "
          "destroyed the editor");
      return NS_ERROR_EDITOR_DESTROYED;
    }
    NS_WARNING_ASSERTION(
        NS_SUCCEEDED(rv),
        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::height) "
        "failed, but ignored");
  }

  if (!styledElement->IsHTMLElement(nsGkAtoms::div) ||
      HTMLEditor::HasStyleOrIdOrClassAttribute(*styledElement)) {
    return NS_OK;
  }

  EditorDOMPoint pointToPutCaret;
  // Make sure the first fild and last child of aElement starts/ends hard
  // line(s) even after removing `aElement`.
  {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    Result<CreateElementResult, nsresult>
        maybeInsertBRElementBeforeFirstChildResult =
            EnsureHardLineBeginsWithFirstChildOf(MOZ_KnownLive(*styledElement));
    if (MOZ_UNLIKELY(maybeInsertBRElementBeforeFirstChildResult.isErr())) {
      NS_WARNING("HTMLEditor::EnsureHardLineBeginsWithFirstChildOf() failed");
      return maybeInsertBRElementBeforeFirstChildResult.unwrapErr();
    }
    CreateElementResult unwrappedResult =
        maybeInsertBRElementBeforeFirstChildResult.unwrap();
    if (unwrappedResult.HasCaretPointSuggestion()) {
      pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
    }
  }
  {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    Result<CreateElementResult, nsresult>
        maybeInsertBRElementAfterLastChildResult =
            EnsureHardLineEndsWithLastChildOf(MOZ_KnownLive(*styledElement));
    if (MOZ_UNLIKELY(maybeInsertBRElementAfterLastChildResult.isErr())) {
      NS_WARNING("HTMLEditor::EnsureHardLineEndsWithLastChildOf() failed");
      return maybeInsertBRElementAfterLastChildResult.unwrapErr();
    }
    CreateElementResult unwrappedResult =
        maybeInsertBRElementAfterLastChildResult.unwrap();
    if (unwrappedResult.HasCaretPointSuggestion()) {
      pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
    }
  }
  {
    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    Result<EditorDOMPoint, nsresult> unwrapStyledElementResult =
        RemoveContainerWithTransaction(MOZ_KnownLive(*styledElement));
    if (MOZ_UNLIKELY(unwrapStyledElementResult.isErr())) {
      NS_WARNING("HTMLEditor::RemoveContainerWithTransaction() failed");
      return unwrapStyledElementResult.unwrapErr();
    }
    if (unwrapStyledElementResult.inspect().IsSet()) {
      pointToPutCaret = unwrapStyledElementResult.unwrap();
    }
  }
  if (!AllowsTransactionsToChangeSelection() || !pointToPutCaret.IsSet()) {
    return NS_OK;
  }
  rv = CollapseSelectionTo(pointToPutCaret);
  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                       "EditorBase::CollapseSelectionTo() failed");
  return rv;
}

NS_IMETHODIMP HTMLEditor::SetSnapToGridEnabled(bool aEnabled) {
  mSnapToGridEnabled = aEnabled;
  return NS_OK;
}

NS_IMETHODIMP HTMLEditor::GetSnapToGridEnabled(bool* aIsEnabled) {
  *aIsEnabled = mSnapToGridEnabled;
  return NS_OK;
}

NS_IMETHODIMP HTMLEditor::SetGridSize(uint32_t aSize) {
  mGridSize = aSize;
  return NS_OK;
}

NS_IMETHODIMP HTMLEditor::GetGridSize(uint32_t* aSize) {
  *aSize = mGridSize;
  return NS_OK;
}

nsresult HTMLEditor::SetTopAndLeftWithTransaction(
    nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
  AutoPlaceholderBatch treatAsOneTransaction(
      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);
  nsresult rv;
  rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(*this, aStyledElement,
                                                         *nsGkAtoms::left, aX);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
      "failed, but ignored");
  rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(*this, aStyledElement,
                                                         *nsGkAtoms::top, aY);
  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    NS_WARNING(
        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
        "destroyed the editor");
    return NS_ERROR_EDITOR_DESTROYED;
  }
  NS_WARNING_ASSERTION(
      NS_SUCCEEDED(rv),
      "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
      "failed, but ignored");
  return NS_OK;
}

nsresult HTMLEditor::GetTemporaryStyleForFocusedPositionedElement(
    Element& aElement, nsAString& aReturn) {
  // we are going to outline the positioned element and bring it to the
  // front to overlap any other element intersecting with it. But
  // first, let's see what's the background and foreground colors of the
  // positioned element.
  // if background-image computed value is 'none,
  //   If the background color is 'auto' and R G B values of the foreground are
  //       each above #d0, use a black background
  //   If the background color is 'auto' and at least one of R G B values of
  //       the foreground is below #d0, use a white background
  // Otherwise don't change background/foreground
  aReturn.Truncate();

  nsAutoString backgroundImageValue;
  nsresult rv = CSSEditUtils::GetComputedProperty(
      aElement, *nsGkAtoms::background_image, backgroundImageValue);
  if (NS_FAILED(rv)) {
    NS_WARNING(
        "CSSEditUtils::GetComputedProperty(nsGkAtoms::background_image) "
        "failed");
    return rv;
  }
  if (!backgroundImageValue.EqualsLiteral("none")) {
    return NS_OK;
  }

  nsAutoString backgroundColorValue;
  rv = CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::backgroundColor,
                                         backgroundColorValue);
  if (NS_FAILED(rv)) {
    NS_WARNING(
        "CSSEditUtils::GetComputedProperty(nsGkAtoms::backgroundColor) "
        "failed");
    return rv;
  }
  if (!backgroundColorValue.EqualsLiteral("rgba(0, 0, 0, 0)")) {
    return NS_OK;
  }

  RefPtr<const ComputedStyle> style =
      nsComputedDOMStyle::GetComputedStyle(&aElement);
  if (NS_WARN_IF(Destroyed())) {
    return NS_ERROR_EDITOR_DESTROYED;
  }
  if (!style) {
    NS_WARNING("nsComputedDOMStyle::GetComputedStyle() failed");
    return NS_ERROR_FAILURE;
  }

  static const uint8_t kBlackBgTrigger = 0xd0;

  auto color = style->StyleText()->mColor.ToColor();
  if (NS_GET_R(color) >= kBlackBgTrigger &&
      NS_GET_G(color) >= kBlackBgTrigger &&
      NS_GET_B(color) >= kBlackBgTrigger) {
    aReturn.AssignLiteral("black");
  } else {
    aReturn.AssignLiteral("white");
  }

  return NS_OK;
}

}  // namespace mozilla

98%


¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.