Skip to content

Commit

Permalink
Bug 1770877 - part 38: Make `HTMLEditor::InsertParagraphSeparatorAsSu…
Browse files Browse the repository at this point in the history
…bAction` stop updating `Selection` while handling its job r=m_kato

Finally, this patch makes it update `Selection` once after finishing its
preparation.

Differential Revision: https://phabricator.services.mozilla.com/D149109
  • Loading branch information
masayuki-nakano committed Jun 22, 2022
1 parent 3e72dba commit c2a64d2
Showing 1 changed file with 42 additions and 74 deletions.
116 changes: 42 additions & 74 deletions editor/libeditor/HTMLEditSubActionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1549,19 +1549,26 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
}
}

if (IsMailEditor()) {
const auto pointToSplit = GetFirstSelectionStartPoint<EditorDOMPoint>();
if (NS_WARN_IF(!pointToSplit.IsInContentNode())) {
return EditActionIgnored(NS_ERROR_FAILURE);
}
AutoRangeArray selectionRanges(SelectionRef());
selectionRanges.EnsureOnlyEditableRanges(aEditingHost);
if (NS_WARN_IF(selectionRanges.Ranges().IsEmpty())) {
return EditActionIgnored(NS_ERROR_FAILURE);
}

auto pointToInsert =
selectionRanges.GetFirstRangeStartPoint<EditorDOMPoint>();
if (NS_WARN_IF(!pointToInsert.IsInContentNode())) {
return EditActionIgnored(NS_ERROR_FAILURE);
}

if (IsMailEditor()) {
if (RefPtr<Element> mailCiteElement = GetMostDistantAncestorMailCiteElement(
*pointToSplit.ContainerAsContent())) {
*pointToInsert.ContainerAsContent())) {
// Split any mailcites in the way. Should we abort this if we encounter
// table cell boundaries?
Result<EditorDOMPoint, nsresult> atNewBRElementOrError =
HandleInsertParagraphInMailCiteElement(*mailCiteElement, pointToSplit,
aEditingHost);
HandleInsertParagraphInMailCiteElement(*mailCiteElement,
pointToInsert, aEditingHost);
if (MOZ_UNLIKELY(atNewBRElementOrError.isErr())) {
NS_WARNING(
"HTMLEditor::HandleInsertParagraphInMailCiteElement() failed");
Expand All @@ -1579,24 +1586,6 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
}
}

// Smart splitting rules
const nsRange* firstRange = SelectionRef().GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return EditActionIgnored(NS_ERROR_FAILURE);
}

EditorDOMPoint atStartOfSelection(firstRange->StartRef());
if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
return EditActionIgnored(NS_ERROR_FAILURE);
}
MOZ_ASSERT(atStartOfSelection.IsSetAndValid());

// Do nothing if the node is read-only
if (!HTMLEditUtils::IsSimplyEditableNode(
*atStartOfSelection.GetContainer())) {
return EditActionCanceled();
}

// If the active editing host is an inline element, or if the active editing
// host is the block parent itself and we're configured to use <br> as a
// paragraph separator, just append a <br>.
Expand All @@ -1608,9 +1597,8 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
// does it.
if (aEditingHost.GetParentElement() &&
HTMLEditUtils::IsSimplyEditableNode(*aEditingHost.GetParentElement()) &&
(!atStartOfSelection.IsInContentNode() ||
!nsContentUtils::ContentIsFlattenedTreeDescendantOf(
atStartOfSelection.ContainerAsContent(), &aEditingHost))) {
!nsContentUtils::ContentIsFlattenedTreeDescendantOf(
pointToInsert.ContainerAsContent(), &aEditingHost)) {
return EditActionHandled(NS_ERROR_EDITOR_NO_EDITABLE_RANGE);
}

Expand Down Expand Up @@ -1664,24 +1652,22 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
// there is no block parent here because in such case, i.e., editing host
// is an inline element, we should insert <br> simply.
RefPtr<Element> editableBlockElement =
atStartOfSelection.IsInContentNode()
? HTMLEditUtils::GetInclusiveAncestorElement(
*atStartOfSelection.ContainerAsContent(),
HTMLEditUtils::ClosestEditableBlockElement)
: nullptr;
HTMLEditUtils::GetInclusiveAncestorElement(
*pointToInsert.ContainerAsContent(),
HTMLEditUtils::ClosestEditableBlockElement);

// If we cannot insert a <p>/<div> element at the selection, we should insert
// a <br> element or a linefeed instead.
const ParagraphSeparator separator = GetDefaultParagraphSeparator();
if (InsertLineBreakInstead(editableBlockElement, atStartOfSelection,
separator, aEditingHost)) {
if (InsertLineBreakInstead(editableBlockElement, pointToInsert, separator,
aEditingHost)) {
// For backward compatibility, we should not insert a linefeed if
// paragraph separator is set to "br" which is Gecko-specific mode.
if (separator != ParagraphSeparator::br &&
HTMLEditUtils::ShouldInsertLinefeedCharacter(atStartOfSelection,
HTMLEditUtils::ShouldInsertLinefeedCharacter(pointToInsert,
aEditingHost)) {
Result<EditorDOMPoint, nsresult> insertLineFeedResult =
HandleInsertLinefeed(atStartOfSelection, aEditingHost);
HandleInsertLinefeed(pointToInsert, aEditingHost);
if (MOZ_UNLIKELY(insertLineFeedResult.isErr())) {
NS_WARNING("HTMLEditor::HandleInsertLinefeed() failed");
return EditActionResult(insertLineFeedResult.unwrapErr());
Expand All @@ -1695,7 +1681,7 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
}

CreateElementResult insertBRElementResult =
HandleInsertBRElement(atStartOfSelection, aEditingHost);
HandleInsertBRElement(pointToInsert, aEditingHost);
if (insertBRElementResult.isErr()) {
NS_WARNING("HTMLEditor::HandleInsertBRElement() failed");
return EditActionHandled(insertBRElementResult.unwrapErr());
Expand All @@ -1713,7 +1699,6 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
// Insert a new block first
MOZ_ASSERT(separator == ParagraphSeparator::div ||
separator == ParagraphSeparator::p);
AutoRangeArray selectionRanges(SelectionRef());
nsresult rv = FormatBlockContainerWithTransaction(
selectionRanges,
MOZ_KnownLive(HTMLEditor::ToParagraphSeparatorTagName(separator)),
Expand All @@ -1725,35 +1710,22 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
if (selectionRanges.HasSavedRanges()) {
selectionRanges.RestoreFromSavedRanges();
}
DebugOnly<nsresult> rvIgnored = selectionRanges.ApplyTo(SelectionRef());
if (NS_WARN_IF(Destroyed())) {
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"AutoRangeArray::ApplyTo(SelectionRef()) failed, but ignored");

firstRange = SelectionRef().GetRangeAt(0);
if (NS_WARN_IF(!firstRange)) {
return EditActionIgnored(NS_ERROR_FAILURE);
}

atStartOfSelection = firstRange->StartRef();
if (NS_WARN_IF(!atStartOfSelection.IsInContentNode())) {
return EditActionIgnored(NS_ERROR_FAILURE);
pointToInsert = selectionRanges.GetFirstRangeStartPoint<EditorDOMPoint>();
if (NS_WARN_IF(!pointToInsert.IsInContentNode())) {
return EditActionIgnored(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
MOZ_ASSERT(pointToInsert.IsSetAndValid());

editableBlockElement = HTMLEditUtils::GetInclusiveAncestorElement(
*atStartOfSelection.ContainerAsContent(),
*pointToInsert.ContainerAsContent(),
HTMLEditUtils::ClosestEditableBlockElement);
if (NS_WARN_IF(!editableBlockElement)) {
return EditActionIgnored(NS_ERROR_UNEXPECTED);
}
if (NS_WARN_IF(!HTMLEditUtils::IsSplittableNode(*editableBlockElement))) {
// Didn't create a new block for some reason, fall back to <br>
CreateElementResult insertBRElementResult =
HandleInsertBRElement(atStartOfSelection, aEditingHost);
HandleInsertBRElement(pointToInsert, aEditingHost);
if (insertBRElementResult.isErr()) {
NS_WARNING("HTMLEditor::HandleInsertBRElement() failed");
return EditActionResult(insertBRElementResult.unwrapErr());
Expand Down Expand Up @@ -1783,7 +1755,6 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
if (HTMLEditUtils::IsEmptyBlockElement(
*editableBlockElement,
{EmptyCheckOption::TreatSingleBRElementAsVisible})) {
AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
CreateElementResult insertBRElementResult = InsertBRElement(
WithTransaction::Yes, EditorDOMPoint::AtEndOf(*editableBlockElement));
if (insertBRElementResult.isErr()) {
Expand All @@ -1793,6 +1764,11 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
insertBRElementResult.IgnoreCaretPointSuggestion();
MOZ_ASSERT(insertBRElementResult.GetNewNode());
insertedPaddingBRElement = insertBRElementResult.UnwrapNewNode();

pointToInsert = selectionRanges.GetFirstRangeStartPoint<EditorDOMPoint>();
if (NS_WARN_IF(!pointToInsert.IsInContentNode())) {
return EditActionHandled(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
}
}

RefPtr<Element> maybeNonEditableListItem =
Expand All @@ -1801,8 +1777,8 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
if (maybeNonEditableListItem &&
HTMLEditUtils::IsSplittableNode(*maybeNonEditableListItem)) {
Result<EditorDOMPoint, nsresult> pointToPutCaretOrError =
HandleInsertParagraphInListItemElement(
*maybeNonEditableListItem, atStartOfSelection, aEditingHost);
HandleInsertParagraphInListItemElement(*maybeNonEditableListItem,
pointToInsert, aEditingHost);
if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
if (NS_WARN_IF(pointToPutCaretOrError.unwrapErr() ==
NS_ERROR_EDITOR_DESTROYED)) {
Expand All @@ -1828,7 +1804,7 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
if (HTMLEditUtils::IsHeader(*editableBlockElement)) {
SplitNodeResult splitHeadingElementResult =
HandleInsertParagraphInHeadingElement(*editableBlockElement,
atStartOfSelection);
pointToInsert);
if (MOZ_UNLIKELY(splitHeadingElementResult.isErr())) {
NS_WARNING("HTMLEditor::HandleInsertParagraphInHeadingElement() failed");
return EditActionHandled();
Expand Down Expand Up @@ -1858,19 +1834,11 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
(separator != ParagraphSeparator::br &&
editableBlockElement->IsAnyOfHTMLElements(nsGkAtoms::p,
nsGkAtoms::div))) {
// TODO: We should work this with atStartOfSelection rather than referring
// current `Selection` again.
const auto firstRangeStartPoint =
EditorBase::GetFirstSelectionStartPoint<EditorDOMPoint>();
if (NS_WARN_IF(!firstRangeStartPoint.IsSet())) {
return EditActionResult(NS_ERROR_FAILURE);
}

// Paragraphs: special rules to look for <br>s
const SplitNodeResult splitResult = HandleInsertParagraphInParagraph(
*editableBlockElement,
insertedPaddingBRElement ? EditorDOMPoint(insertedPaddingBRElement)
: atStartOfSelection,
: pointToInsert,
aEditingHost);
if (splitResult.isErr()) {
NS_WARNING("HTMLEditor::HandleInsertParagraphInParagraph() failed");
Expand All @@ -1893,14 +1861,14 @@ EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction(
// Fall through, if HandleInsertParagraphInParagraph() didn't handle it.
MOZ_ASSERT(!result.Canceled());
MOZ_ASSERT(result.Rv() == NS_SUCCESS_DOM_NO_OPERATION);
MOZ_ASSERT(atStartOfSelection.IsSetAndValid(),
MOZ_ASSERT(pointToInsert.IsSetAndValid(),
"HTMLEditor::HandleInsertParagraphInParagraph() shouldn't touch "
"the DOM tree if it returns not-handled state");
}

// If nobody handles this edit action, let's insert new <br> at the selection.
CreateElementResult insertBRElementResult =
HandleInsertBRElement(atStartOfSelection, aEditingHost);
HandleInsertBRElement(pointToInsert, aEditingHost);
if (insertBRElementResult.isErr()) {
NS_WARNING("HTMLEditor::HandleInsertBRElement() failed");
return EditActionIgnored(insertBRElementResult.unwrapErr());
Expand Down

0 comments on commit c2a64d2

Please sign in to comment.