Bug 1990586 - Make WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt track given caret point a=pascalc
It's used as the result in some cases. However, it's not tracked in some cases when touching the DOM. This modifies the API of `AutoTrackDOMPoint` to flush the tracking point but can keep tracking. We should use the new API in every place later. (This manually merges `WhiteSpaceVisibilityKeeper.cpp` because ESR140 still has the pref to take the legacy mode back and that blocks applying the patch cleanly.) Differential Revision: https://phabricator.services.mozilla.com/D270643
This commit is contained in:
committed by
pchevrel@mozilla.com
parent
3c22b4c56f
commit
0c6404cf72
@@ -46,6 +46,7 @@ enum class EditorCommandParamType : uint16_t; // mozilla/EditorCommands.h
|
|||||||
enum class EditSubAction : int32_t; // mozilla/EditAction.h
|
enum class EditSubAction : int32_t; // mozilla/EditAction.h
|
||||||
enum class ParagraphSeparator; // mozilla/HTMLEditor.h
|
enum class ParagraphSeparator; // mozilla/HTMLEditor.h
|
||||||
enum class SpecifiedStyle : uint8_t; // mozilla/PendingStyles.h
|
enum class SpecifiedStyle : uint8_t; // mozilla/PendingStyles.h
|
||||||
|
enum class StopTracking : bool; // mozilla/SelectionState.h
|
||||||
enum class SuggestCaret; // EditorUtils.h
|
enum class SuggestCaret; // EditorUtils.h
|
||||||
enum class WithTransaction; // HTMLEditHelpers.h
|
enum class WithTransaction; // HTMLEditHelpers.h
|
||||||
|
|
||||||
|
|||||||
@@ -284,6 +284,8 @@ class MOZ_STACK_CLASS RangeUpdater final {
|
|||||||
bool mLocked;
|
bool mLocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class StopTracking : bool { No, Yes };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for using SelectionState. Stack based class for doing
|
* Helper class for using SelectionState. Stack based class for doing
|
||||||
* preservation of dom points across editor actions.
|
* preservation of dom points across editor actions.
|
||||||
@@ -331,11 +333,13 @@ class MOZ_STACK_CLASS AutoTrackDOMPoint final {
|
|||||||
|
|
||||||
~AutoTrackDOMPoint() { FlushAndStopTracking(); }
|
~AutoTrackDOMPoint() { FlushAndStopTracking(); }
|
||||||
|
|
||||||
void FlushAndStopTracking() {
|
void Flush(StopTracking aStopTracking) {
|
||||||
if (!mIsTracking) {
|
if (!mIsTracking) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mIsTracking = false;
|
if (static_cast<bool>(aStopTracking)) {
|
||||||
|
mIsTracking = false;
|
||||||
|
}
|
||||||
if (mPoint.isSome()) {
|
if (mPoint.isSome()) {
|
||||||
mRangeUpdater.DropRangeItem(mRangeItem);
|
mRangeUpdater.DropRangeItem(mRangeItem);
|
||||||
// Setting `mPoint` with invalid DOM point causes hitting `NS_ASSERTION()`
|
// Setting `mPoint` with invalid DOM point causes hitting `NS_ASSERTION()`
|
||||||
@@ -378,6 +382,8 @@ class MOZ_STACK_CLASS AutoTrackDOMPoint final {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FlushAndStopTracking() { Flush(StopTracking::Yes); }
|
||||||
|
|
||||||
void StopTracking() { mIsTracking = false; }
|
void StopTracking() { mIsTracking = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -3450,6 +3450,11 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
MOZ_ASSERT(
|
MOZ_ASSERT(
|
||||||
StaticPrefs::editor_white_space_normalization_blink_compatible());
|
StaticPrefs::editor_white_space_normalization_blink_compatible());
|
||||||
|
|
||||||
|
Maybe<AutoTrackDOMPoint> trackPointToPutCaret;
|
||||||
|
if (aCaretPoint.IsSet()) {
|
||||||
|
trackPointToPutCaret.emplace(aHTMLEditor.RangeUpdaterRef(),
|
||||||
|
&pointToPutCaret);
|
||||||
|
}
|
||||||
// If we're removing a block, it may be surrounded by invisible
|
// If we're removing a block, it may be surrounded by invisible
|
||||||
// white-spaces. We should remove them to avoid to make them accidentally
|
// white-spaces. We should remove them to avoid to make them accidentally
|
||||||
// visible.
|
// visible.
|
||||||
@@ -3459,8 +3464,6 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
AutoTrackDOMPoint trackAtContent(aHTMLEditor.RangeUpdaterRef(),
|
AutoTrackDOMPoint trackAtContent(aHTMLEditor.RangeUpdaterRef(),
|
||||||
&atContent);
|
&atContent);
|
||||||
{
|
{
|
||||||
AutoTrackDOMPoint trackPointToPutCaret(aHTMLEditor.RangeUpdaterRef(),
|
|
||||||
&pointToPutCaret);
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
WhiteSpaceVisibilityKeeper::EnsureNoInvisibleWhiteSpacesBefore(
|
WhiteSpaceVisibilityKeeper::EnsureNoInvisibleWhiteSpacesBefore(
|
||||||
aHTMLEditor, EditorDOMPoint(aContentToDelete.AsElement()));
|
aHTMLEditor, EditorDOMPoint(aContentToDelete.AsElement()));
|
||||||
@@ -3484,6 +3487,9 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
if (NS_WARN_IF(!aContentToDelete.IsInComposedDoc())) {
|
if (NS_WARN_IF(!aContentToDelete.IsInComposedDoc())) {
|
||||||
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
||||||
}
|
}
|
||||||
|
if (trackPointToPutCaret.isSome()) {
|
||||||
|
trackPointToPutCaret->Flush(StopTracking::No);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pointToPutCaret.IsInContentNode()) {
|
if (pointToPutCaret.IsInContentNode()) {
|
||||||
// Additionally, we may put caret into the preceding block (this is the
|
// Additionally, we may put caret into the preceding block (this is the
|
||||||
@@ -3558,7 +3564,7 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trackAtContent.FlushAndStopTracking();
|
trackAtContent.Flush(StopTracking::Yes);
|
||||||
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
||||||
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
||||||
}
|
}
|
||||||
@@ -3584,7 +3590,7 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
"failed");
|
"failed");
|
||||||
return afterLastVisibleThingOrError.propagateErr();
|
return afterLastVisibleThingOrError.propagateErr();
|
||||||
}
|
}
|
||||||
trackAtContent.FlushAndStopTracking();
|
trackAtContent.Flush(StopTracking::Yes);
|
||||||
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
||||||
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
||||||
}
|
}
|
||||||
@@ -3604,7 +3610,7 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesBefore() failed");
|
"WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesBefore() failed");
|
||||||
return atFirstVisibleThingOrError.propagateErr();
|
return atFirstVisibleThingOrError.propagateErr();
|
||||||
}
|
}
|
||||||
trackAtContent.FlushAndStopTracking();
|
trackAtContent.Flush(StopTracking::Yes);
|
||||||
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
if (NS_WARN_IF(!atContent.IsInContentNodeAndValidInComposedDoc())) {
|
||||||
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
||||||
}
|
}
|
||||||
@@ -3616,13 +3622,22 @@ WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
|||||||
aContentToDelete, {WalkTreeOption::IgnoreNonEditableNode});
|
aContentToDelete, {WalkTreeOption::IgnoreNonEditableNode});
|
||||||
// Delete the node, and join like nodes if appropriate
|
// Delete the node, and join like nodes if appropriate
|
||||||
{
|
{
|
||||||
AutoTrackDOMPoint trackPointToPutCaret(aHTMLEditor.RangeUpdaterRef(),
|
Maybe<AutoTrackDOMPoint> trackPointToPutCaret;
|
||||||
&pointToPutCaret);
|
if (pointToPutCaret.IsSet()) {
|
||||||
|
trackPointToPutCaret.emplace(aHTMLEditor.RangeUpdaterRef(),
|
||||||
|
&pointToPutCaret);
|
||||||
|
}
|
||||||
nsresult rv = aHTMLEditor.DeleteNodeWithTransaction(aContentToDelete);
|
nsresult rv = aHTMLEditor.DeleteNodeWithTransaction(aContentToDelete);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
|
NS_WARNING("EditorBase::DeleteNodeWithTransaction() failed");
|
||||||
return Err(rv);
|
return Err(rv);
|
||||||
}
|
}
|
||||||
|
if (trackPointToPutCaret.isSome()) {
|
||||||
|
trackPointToPutCaret->Flush(StopTracking::Yes);
|
||||||
|
if (NS_WARN_IF(!pointToPutCaret.IsInContentNode())) {
|
||||||
|
return Err(NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are they both text nodes? If so, join them!
|
// Are they both text nodes? If so, join them!
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
addEventListener("DOMContentLoaded", () => {
|
||||||
|
document.documentElement.contentEditable = "plaintext-only";
|
||||||
|
document.execCommand("delete");
|
||||||
|
}, {once: true});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<track></track>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user