Bug 1770877 - part 33: Make HTMLEditor::RelativeFontChangeOnTextNode stop touching Selection directly r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D149104
This commit is contained in:
Masayuki Nakano
2022-06-22 08:18:40 +00:00
parent 788f5cd59f
commit db9c8aa4f4
4 changed files with 154 additions and 139 deletions

View File

@@ -2547,13 +2547,17 @@ nsresult HTMLEditor::RelativeFontChange(FontSize aDir) {
MOZ_ASSERT(startNode);
MOZ_ASSERT(endNode);
if (startNode == endNode && startNode->IsText()) {
nsresult rv = RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*startNode->GetAsText()), range->StartOffset(),
range->EndOffset());
if (NS_FAILED(rv)) {
CreateElementResult wrapWithBigOrSmallElementResult =
RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*startNode->GetAsText()),
range->StartOffset(), range->EndOffset());
if (wrapWithBigOrSmallElementResult.isErr()) {
NS_WARNING("HTMLEditor::RelativeFontChangeOnTextNode() failed");
return rv;
return wrapWithBigOrSmallElementResult.unwrapErr();
}
// There is an AutoTransactionsConserveSelection instance so that we don't
// need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion();
} else {
// Not the easy case. Range not contained in single text node. There
// are up to three phases here. There are all the nodes reported by the
@@ -2599,22 +2603,30 @@ nsresult HTMLEditor::RelativeFontChange(FontSize aDir) {
// the subtree iterator works - it will not have reported them).
if (startNode->IsText() && EditorUtils::IsEditableContent(
*startNode->AsText(), EditorType::HTML)) {
nsresult rv = RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*startNode->AsText()), range->StartOffset(),
startNode->Length());
if (NS_FAILED(rv)) {
CreateElementResult wrapWithBigOrSmallElementResult =
RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*startNode->AsText()), range->StartOffset(),
startNode->Length());
if (wrapWithBigOrSmallElementResult.isErr()) {
NS_WARNING("HTMLEditor::RelativeFontChangeOnTextNode() failed");
return rv;
return wrapWithBigOrSmallElementResult.unwrapErr();
}
// There is an AutoTransactionsConserveSelection instance so that we
// don't need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion();
}
if (endNode->IsText() && EditorUtils::IsEditableContent(
*endNode->AsText(), EditorType::HTML)) {
nsresult rv = RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*endNode->AsText()), 0, range->EndOffset());
if (NS_FAILED(rv)) {
CreateElementResult wrapWithBigOrSmallElementResult =
RelativeFontChangeOnTextNode(
aDir, MOZ_KnownLive(*endNode->AsText()), 0, range->EndOffset());
if (wrapWithBigOrSmallElementResult.isErr()) {
NS_WARNING("HTMLEditor::RelativeFontChangeOnTextNode() failed");
return rv;
return wrapWithBigOrSmallElementResult.unwrapErr();
}
// There is an AutoTransactionsConserveSelection instance so that we
// don't need to update selection for this change.
wrapWithBigOrSmallElementResult.IgnoreCaretPointSuggestion();
}
}
}
@@ -2622,19 +2634,18 @@ nsresult HTMLEditor::RelativeFontChange(FontSize aDir) {
return NS_OK;
}
nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
Text& aTextNode,
uint32_t aStartOffset,
uint32_t aEndOffset) {
CreateElementResult HTMLEditor::RelativeFontChangeOnTextNode(
FontSize aDir, Text& aTextNode, uint32_t aStartOffset,
uint32_t aEndOffset) {
// Don't need to do anything if no characters actually selected
if (aStartOffset == aEndOffset) {
return NS_OK;
return CreateElementResult::NotHandled();
}
if (!aTextNode.GetParentNode() ||
!HTMLEditUtils::CanNodeContain(*aTextNode.GetParentNode(),
*nsGkAtoms::big)) {
return NS_OK;
return CreateElementResult::NotHandled();
}
aEndOffset = std::min(aTextNode.Length(), aEndOffset);
@@ -2642,77 +2653,70 @@ nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
// Make the range an independent node.
RefPtr<Text> textNodeForTheRange = &aTextNode;
auto pointToPutCaretOrError =
[&]() MOZ_CAN_RUN_SCRIPT -> Result<EditorDOMPoint, nsresult> {
EditorDOMPoint pointToPutCaret;
// Split at the end of the range.
EditorDOMPoint atEnd(textNodeForTheRange, aEndOffset);
if (!atEnd.IsEndOfContainer()) {
// We need to split off back of text node
SplitNodeResult splitAtEndResult = SplitNodeWithTransaction(atEnd);
if (splitAtEndResult.isErr()) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(splitAtEndResult.unwrapErr());
EditorDOMPoint pointToPutCaret;
{
auto pointToPutCaretOrError =
[&]() MOZ_CAN_RUN_SCRIPT -> Result<EditorDOMPoint, nsresult> {
EditorDOMPoint pointToPutCaret;
// Split at the end of the range.
EditorDOMPoint atEnd(textNodeForTheRange, aEndOffset);
if (!atEnd.IsEndOfContainer()) {
// We need to split off back of text node
SplitNodeResult splitAtEndResult = SplitNodeWithTransaction(atEnd);
if (splitAtEndResult.isErr()) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(splitAtEndResult.unwrapErr());
}
if (MOZ_UNLIKELY(!splitAtEndResult.HasCaretPointSuggestion())) {
NS_WARNING(
"HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
"point");
return Err(NS_ERROR_FAILURE);
}
splitAtEndResult.MoveCaretPointTo(pointToPutCaret, *this, {});
MOZ_ASSERT_IF(AllowsTransactionsToChangeSelection(),
pointToPutCaret.IsSet());
textNodeForTheRange =
Text::FromNodeOrNull(splitAtEndResult.GetPreviousContent());
MOZ_DIAGNOSTIC_ASSERT(textNodeForTheRange);
// When adding caret suggestion to SplitNodeResult, here didn't change
// selection so that just ignore it.
splitAtEndResult.IgnoreCaretPointSuggestion();
}
if (MOZ_UNLIKELY(!splitAtEndResult.HasCaretPointSuggestion())) {
NS_WARNING(
"HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
"point");
return Err(NS_ERROR_FAILURE);
}
splitAtEndResult.MoveCaretPointTo(
pointToPutCaret, *this,
{SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
MOZ_ASSERT_IF(AllowsTransactionsToChangeSelection(),
pointToPutCaret.IsSet());
textNodeForTheRange =
Text::FromNodeOrNull(splitAtEndResult.GetPreviousContent());
MOZ_DIAGNOSTIC_ASSERT(textNodeForTheRange);
// When adding caret suggestion to SplitNodeResult, here didn't change
// selection so that just ignore it.
splitAtEndResult.IgnoreCaretPointSuggestion();
}
// Split at the start of the range.
EditorDOMPoint atStart(textNodeForTheRange, aStartOffset);
if (!atStart.IsStartOfContainer()) {
// We need to split off front of text node
SplitNodeResult splitAtStartResult = SplitNodeWithTransaction(atStart);
if (splitAtStartResult.isErr()) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(splitAtStartResult.unwrapErr());
// Split at the start of the range.
EditorDOMPoint atStart(textNodeForTheRange, aStartOffset);
if (!atStart.IsStartOfContainer()) {
// We need to split off front of text node
SplitNodeResult splitAtStartResult = SplitNodeWithTransaction(atStart);
if (splitAtStartResult.isErr()) {
NS_WARNING("HTMLEditor::SplitNodeWithTransaction() failed");
return Err(splitAtStartResult.unwrapErr());
}
if (MOZ_UNLIKELY(!splitAtStartResult.HasCaretPointSuggestion())) {
NS_WARNING(
"HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
"point");
return Err(NS_ERROR_FAILURE);
}
splitAtStartResult.MoveCaretPointTo(pointToPutCaret, *this, {});
MOZ_ASSERT_IF(AllowsTransactionsToChangeSelection(),
pointToPutCaret.IsSet());
textNodeForTheRange =
Text::FromNodeOrNull(splitAtStartResult.GetNextContent());
MOZ_DIAGNOSTIC_ASSERT(textNodeForTheRange);
// When adding caret suggestion to SplitNodeResult, here didn't change
// selection so that just ignore it.
splitAtStartResult.IgnoreCaretPointSuggestion();
}
if (MOZ_UNLIKELY(!splitAtStartResult.HasCaretPointSuggestion())) {
NS_WARNING(
"HTMLEditor::SplitNodeWithTransaction() didn't suggest caret "
"point");
return Err(NS_ERROR_FAILURE);
}
splitAtStartResult.MoveCaretPointTo(
pointToPutCaret, *this,
{SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
MOZ_ASSERT_IF(AllowsTransactionsToChangeSelection(),
pointToPutCaret.IsSet());
textNodeForTheRange =
Text::FromNodeOrNull(splitAtStartResult.GetNextContent());
MOZ_DIAGNOSTIC_ASSERT(textNodeForTheRange);
// When adding caret suggestion to SplitNodeResult, here didn't change
// selection so that just ignore it.
splitAtStartResult.IgnoreCaretPointSuggestion();
}
return pointToPutCaret;
}();
if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
// Don't warn here since it should be done in the lambda.
return pointToPutCaretOrError.unwrapErr();
}
if (pointToPutCaretOrError.inspect().IsSet()) {
nsresult rv = CollapseSelectionTo(pointToPutCaretOrError.inspect());
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("EditorBase::CollapseSelectionTo() failed");
return rv;
return pointToPutCaret;
}();
if (MOZ_UNLIKELY(pointToPutCaretOrError.isErr())) {
// Don't warn here since it should be done in the lambda.
return CreateElementResult(pointToPutCaretOrError.unwrapErr());
}
pointToPutCaret = pointToPutCaretOrError.unwrap();
}
// Look for siblings that are correct type of node
@@ -2722,70 +2726,46 @@ nsresult HTMLEditor::RelativeFontChangeOnTextNode(FontSize aDir,
*textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode});
if (sibling && sibling->IsHTMLElement(bigOrSmallTagName)) {
// Previous sib is already right kind of inline node; slide this over
const MoveNodeResult moveTextNodeResult =
MoveNodeResult moveTextNodeResult =
MoveNodeToEndWithTransaction(*textNodeForTheRange, *sibling);
if (moveTextNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeToEndWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
return CreateElementResult(moveTextNodeResult.unwrapErr());
}
nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv;
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
moveTextNodeResult.MoveCaretPointTo(pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion});
// XXX Should we return the new container?
return CreateElementResult::NotHandled(std::move(pointToPutCaret));
}
sibling = HTMLEditUtils::GetNextSibling(
*textNodeForTheRange, {WalkTreeOption::IgnoreNonEditableNode});
if (sibling && sibling->IsHTMLElement(bigOrSmallTagName)) {
// Following sib is already right kind of inline node; slide this over
const MoveNodeResult moveTextNodeResult = MoveNodeWithTransaction(
MoveNodeResult moveTextNodeResult = MoveNodeWithTransaction(
*textNodeForTheRange, EditorDOMPoint(sibling, 0u));
if (moveTextNodeResult.isErr()) {
NS_WARNING("HTMLEditor::MoveNodeWithTransaction() failed");
return moveTextNodeResult.unwrapErr();
return CreateElementResult(moveTextNodeResult.unwrapErr());
}
nsresult rv = moveTextNodeResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("MoveNodeResult::SuggestCaretPointTo() failed");
return rv;
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"MoveNodeResult::SuggestCaretPointTo() failed, but ignored");
return NS_OK;
moveTextNodeResult.MoveCaretPointTo(pointToPutCaret, *this,
{SuggestCaret::OnlyIfHasSuggestion});
// XXX Should we return the new container?
return CreateElementResult::NotHandled(std::move(pointToPutCaret));
}
// Else wrap the node inside font node with appropriate relative size
const CreateElementResult wrapTextWithBigOrSmallElementResult =
CreateElementResult wrapTextWithBigOrSmallElementResult =
InsertContainerWithTransaction(*textNodeForTheRange,
MOZ_KnownLive(*bigOrSmallTagName));
if (wrapTextWithBigOrSmallElementResult.isErr()) {
NS_WARNING("HTMLEditor::InsertContainerWithTransaction() failed");
return wrapTextWithBigOrSmallElementResult.inspectErr();
return wrapTextWithBigOrSmallElementResult;
}
MOZ_ASSERT(wrapTextWithBigOrSmallElementResult.GetNewNode());
nsresult rv = wrapTextWithBigOrSmallElementResult.SuggestCaretPointTo(
*this, {SuggestCaret::OnlyIfHasSuggestion,
SuggestCaret::OnlyIfTransactionsAllowedToDoIt,
SuggestCaret::AndIgnoreTrivialError});
if (NS_FAILED(rv)) {
NS_WARNING("CreateElementResult::SuggestCaretPointTo() failed");
return rv;
}
NS_WARNING_ASSERTION(
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
"CreateElementResult::SuggestCaretPointTo() failed, but ignored");
return rv;
wrapTextWithBigOrSmallElementResult.MoveCaretPointTo(
pointToPutCaret, {SuggestCaret::OnlyIfHasSuggestion});
return CreateElementResult(
wrapTextWithBigOrSmallElementResult.UnwrapNewNode(),
std::move(pointToPutCaret));
}
nsresult HTMLEditor::RelativeFontChangeHelper(int32_t aSizeChange,