Bug 1766355 - part 6: Make `HTMLEditor::MoveOneHardLineContents` return `MoveNodeResult` with caret point suggestion r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D146402
This commit is contained in:
Masayuki Nakano 2022-05-20 08:51:41 +00:00
Родитель 48083b339b
Коммит e0d3f2aa96
3 изменённых файлов: 64 добавлений и 88 удалений

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

@ -2098,8 +2098,9 @@ class HTMLEditor final : public EditorBase,
ErrorResult& aError);
/**
* MoveOneHardLineContents() moves the content in a hard line which contains
* aPointInHardLine to aPointToInsert or end of aPointToInsert's container.
* MoveOneHardLineContentsWithTransaction() moves the content in a hard line
* which contains aPointInHardLine to aPointToInsert or end of
* aPointToInsert's container.
*
* @param aPointInHardLine A point in a hard line. All nodes in
* same hard line will be moved.
@ -2116,7 +2117,8 @@ class HTMLEditor final : public EditorBase,
* container while we're moving nodes.
*/
enum class MoveToEndOfContainer { Yes, No };
[[nodiscard]] MOZ_CAN_RUN_SCRIPT MoveNodeResult MoveOneHardLineContents(
[[nodiscard]] MOZ_CAN_RUN_SCRIPT MoveNodeResult
MoveOneHardLineContentsWithTransaction(
const EditorDOMPoint& aPointInHardLine,
const EditorDOMPoint& aPointToInsert,
MoveToEndOfContainer aMoveToEndOfContainer = MoveToEndOfContainer::No);
@ -4670,7 +4672,7 @@ class HTMLEditor final : public EditorBase,
// DeleteTextAndTextNodesWithTransaction,
// JoinNearestEditableNodesWithTransaction,
// MoveChildrenWithTransaction,
// MoveOneHardLineContents,
// MoveOneHardLineContentsWithTransaction,
// MoveToEndOfCOntainer,
// SplitAncestorStyledInlineElementsAt,
// TreatEmptyTextNodes

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

@ -4673,8 +4673,9 @@ Result<bool, nsresult> HTMLEditor::CanMoveOrDeleteSomethingInHardLine(
// If there is only a padding `<br>` element in a empty block, it's selected
// by `SelectBRElementIfCollapsedInEmptyBlock()`. However, it won't be
// moved. Although it'll be deleted, `MoveOneHardLineContents()` returns
// "ignored". Therefore, we should return `false` in this case.
// moved. Although it'll be deleted,
// `MoveOneHardLineContentsWithTransaction()` returns "ignored". Therefore,
// we should return `false` in this case.
if (nsIContent* childContent = oneLineRange->GetChildAtStartOffset()) {
if (childContent->IsHTMLElement(nsGkAtoms::br) &&
childContent->GetParent()) {
@ -4735,7 +4736,7 @@ Result<bool, nsresult> HTMLEditor::CanMoveOrDeleteSomethingInHardLine(
return startPoint.GetNextSiblingOfChild() != endPoint.GetChild();
}
MoveNodeResult HTMLEditor::MoveOneHardLineContents(
MoveNodeResult HTMLEditor::MoveOneHardLineContentsWithTransaction(
const EditorDOMPoint& aPointInHardLine,
const EditorDOMPoint& aPointToInsert,
MoveToEndOfContainer
@ -4764,89 +4765,54 @@ MoveNodeResult HTMLEditor::MoveOneHardLineContents(
return MoveNodeIgnored(std::move(pointToInsert));
}
uint32_t offset = pointToInsert.Offset();
MoveNodeResult moveContentsInLineResult;
MoveNodeResult moveContentsInLineResult = MoveNodeIgnored(pointToInsert);
for (auto& content : arrayOfContents) {
if (aMoveToEndOfContainer == MoveToEndOfContainer::Yes) {
// For backward compatibility, we should move contents to end of the
// container if this is called with MoveToEndOfContainer::Yes.
offset = pointToInsert.GetContainer()->Length();
// For backward compatibility, we should move contents to end of the
// container if this is called with MoveToEndOfContainer::Yes.
// And also if pointToInsert has been made invalid with removing preceding
// children, we should move the content to the end of the container.
if (aMoveToEndOfContainer == MoveToEndOfContainer::Yes ||
(MayHaveMutationEventListeners() &&
MOZ_UNLIKELY(!moveContentsInLineResult.NextInsertionPointRef()
.IsSetAndValid()))) {
pointToInsert.SetToEndOf(pointToInsert.GetContainer());
} else {
MOZ_DIAGNOSTIC_ASSERT(
moveContentsInLineResult.NextInsertionPointRef().IsSet());
pointToInsert = moveContentsInLineResult.NextInsertionPointRef();
}
// get the node to act on
// If the content is a block element, move all children of it to the
// new container, and then, remove the (probably) empty block element.
if (HTMLEditUtils::IsBlockElement(content)) {
// For block nodes, move their contents only, then delete block.
moveContentsInLineResult |= MoveChildrenWithTransaction(
MOZ_KnownLive(*content->AsElement()),
EditorDOMPoint(pointToInsert.GetContainer(), offset));
MOZ_KnownLive(*content->AsElement()), pointToInsert);
if (moveContentsInLineResult.isErr()) {
NS_WARNING("HTMLEditor::MoveChildrenWithTransaction() failed");
return moveContentsInLineResult;
}
nsresult rv = moveContentsInLineResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return MoveNodeResult(rv);
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
offset = moveContentsInLineResult.NextInsertionPointRef().Offset();
moveContentsInLineResult.MarkAsHandled();
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to
// keep it alive.
DebugOnly<nsresult> rvIgnored =
DeleteNodeWithTransaction(MOZ_KnownLive(*content));
if (NS_WARN_IF(Destroyed())) {
moveContentsInLineResult.IgnoreCaretPointSuggestion();
return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"HTMLEditor::DeleteNodeWithTransaction() failed, but ignored");
moveContentsInLineResult.MarkAsHandled();
if (MayHaveMutationEventListeners()) {
// Mutation event listener may make `offset` value invalid with
// removing some previous children while we call
// `DeleteNodeWithTransaction()` so that we should adjust it here.
offset = std::min(offset, pointToInsert.GetContainer()->Length());
}
continue;
}
// XXX Different from the above block, we ignore error of moving nodes.
// MOZ_KnownLive because 'arrayOfContents' is guaranteed to
// keep it alive.
MoveNodeResult moveNodeResult = MoveNodeOrChildrenWithTransaction(
MOZ_KnownLive(content),
EditorDOMPoint(pointToInsert.GetContainer(), offset));
if (NS_WARN_IF(moveNodeResult.EditorDestroyed())) {
moveContentsInLineResult.IgnoreCaretPointSuggestion();
return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
moveContentsInLineResult |= MoveNodeOrChildrenWithTransaction(
MOZ_KnownLive(content), pointToInsert);
if (moveContentsInLineResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeOrChildrenWithTransaction() failed");
return moveContentsInLineResult;
}
if (moveNodeResult.isErr()) {
NS_WARNING(
"HTMLEditor::MoveNodeOrChildrenWithTransaction() failed, but "
"ignored");
continue;
}
nsresult rv = moveNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return MoveNodeResult(rv);
}
NS_WARNING_ASSERTION(
rv != NS_ERROR_EDITOR_NO_EDITABLE_RANGE,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
offset = moveNodeResult.NextInsertionPointRef().Offset();
moveContentsInLineResult |= moveNodeResult;
}
NS_WARNING_ASSERTION(
moveContentsInLineResult.isOk(),
"Last HTMLEditor::MoveNodeOrChildrenWithTransaction() failed");
return moveContentsInLineResult;
}

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

@ -276,7 +276,8 @@ EditActionResult WhiteSpaceVisibilityKeeper::
// behavior, we should mark as handled.
ret.MarkAsHandled();
} else {
// XXX Why do we ignore the result of MoveOneHardLineContents()?
// XXX Why do we ignore the result of
// MoveOneHardLineContentsWithTransaction()?
NS_ASSERTION(rightBlockElement == afterRightBlockChild.GetContainer(),
"The relation is not guaranteed but assumed");
#ifdef DEBUG
@ -284,16 +285,18 @@ EditActionResult WhiteSpaceVisibilityKeeper::
aHTMLEditor.CanMoveOrDeleteSomethingInHardLine(EditorRawDOMPoint(
rightBlockElement, afterRightBlockChild.Offset()));
#endif // #ifdef DEBUG
MoveNodeResult moveNodeResult = aHTMLEditor.MoveOneHardLineContents(
EditorDOMPoint(rightBlockElement, afterRightBlockChild.Offset()),
EditorDOMPoint(&aLeftBlockElement, 0u),
HTMLEditor::MoveToEndOfContainer::Yes);
MoveNodeResult moveNodeResult =
aHTMLEditor.MoveOneHardLineContentsWithTransaction(
EditorDOMPoint(rightBlockElement, afterRightBlockChild.Offset()),
EditorDOMPoint(&aLeftBlockElement, 0u),
HTMLEditor::MoveToEndOfContainer::Yes);
if (moveNodeResult.isErr()) {
NS_WARNING(
"HTMLEditor::MoveOneHardLineContents(MoveToEndOfContainer::Yes) "
"failed");
"HTMLEditor::MoveOneHardLineContentsWithTransaction("
"MoveToEndOfContainer::Yes) failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
#ifdef DEBUG
MOZ_ASSERT(!firstLineHasContent.isErr());
if (firstLineHasContent.inspect()) {
@ -304,8 +307,9 @@ EditActionResult WhiteSpaceVisibilityKeeper::
"Failed to consider whether moving or not something");
}
#endif // #ifdef DEBUG
// When MoveNodeResult starts to store caret point, here does not do
// nothing.
// We don't need to update selection here because of dontChangeMySelection
// above.
moveNodeResult.IgnoreCaretPointSuggestion();
ret |= moveNodeResult;
// Now, all children of rightBlockElement were moved to leftBlockElement.
@ -552,10 +556,11 @@ EditActionResult WhiteSpaceVisibilityKeeper::
MOZ_DIAGNOSTIC_ASSERT(atPreviousContent.IsSetAndValid());
}
MoveNodeResult moveNodeResult = aHTMLEditor.MoveOneHardLineContents(
EditorDOMPoint(&aRightBlockElement, 0u), atPreviousContent);
MoveNodeResult moveNodeResult =
aHTMLEditor.MoveOneHardLineContentsWithTransaction(
EditorDOMPoint(&aRightBlockElement, 0u), atPreviousContent);
if (moveNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveOneHardLineContents() failed");
NS_WARNING("HTMLEditor::MoveOneHardLineContentsWithTransaction() failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
@ -569,8 +574,9 @@ EditActionResult WhiteSpaceVisibilityKeeper::
"Failed to consider whether moving or not something");
}
#endif // #ifdef DEBUG
// When MoveNodeResult starts to store caret point, here does not do
// nothing.
// We don't need to update selection here because of dontChangeMySelection
// above.
moveNodeResult.IgnoreCaretPointSuggestion();
ret |= moveNodeResult;
}
@ -664,14 +670,15 @@ EditActionResult WhiteSpaceVisibilityKeeper::
#endif // #ifdef DEBUG
// Nodes are dissimilar types.
MoveNodeResult moveNodeResult = aHTMLEditor.MoveOneHardLineContents(
EditorDOMPoint(&aRightBlockElement, 0u),
EditorDOMPoint(&aLeftBlockElement, 0u),
HTMLEditor::MoveToEndOfContainer::Yes);
MoveNodeResult moveNodeResult =
aHTMLEditor.MoveOneHardLineContentsWithTransaction(
EditorDOMPoint(&aRightBlockElement, 0u),
EditorDOMPoint(&aLeftBlockElement, 0u),
HTMLEditor::MoveToEndOfContainer::Yes);
if (moveNodeResult.isErr()) {
NS_WARNING(
"HTMLEditor::MoveOneHardLineContents(MoveToEndOfContainer::Yes) "
"failed");
"HTMLEditor::MoveOneHardLineContentsWithTransaction("
"MoveToEndOfContainer::Yes) failed");
return EditActionResult(moveNodeResult.unwrapErr());
}
@ -685,8 +692,9 @@ EditActionResult WhiteSpaceVisibilityKeeper::
"Failed to consider whether moving or not something");
}
#endif // #ifdef DEBUG
// When MoveNodeResult starts to store caret point, here does not do
// nothing.
// We don't need to update selection here because of dontChangeMySelection
// above.
moveNodeResult.IgnoreCaretPointSuggestion();
ret |= moveNodeResult;
}