mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 1815827 - part 2: Get rid of editor.hr_element.allow_to_delete_from_following_line
pref r=m_kato
Depends on D169760 Differential Revision: https://phabricator.services.mozilla.com/D169761
This commit is contained in:
parent
3fa7da3abb
commit
b29a944ac4
@ -263,8 +263,7 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||
/**
|
||||
* Handle deletion of atomic elements like <br>, <hr>, <img>, <input>, etc and
|
||||
* data nodes except text node (e.g., comment node). Note that don't call this
|
||||
* directly with `<hr>` element. Instead, call HandleDeleteHRElement().
|
||||
* Note that don't call this for invisible `<br>` element.
|
||||
* directly with `<hr>` element.
|
||||
*
|
||||
* @param aAtomicContent The atomic content to be deleted.
|
||||
* @param aCaretPoint The caret point (i.e., selection start or
|
||||
@ -299,35 +298,6 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||
const WSRunScanner& aWSRunScannerAtCaret,
|
||||
const WSScanResult& aScanFromCaretPointResult) MOZ_NONNULL_RETURN;
|
||||
|
||||
/**
|
||||
* Handle deletion around `<hr>` element. If aDirectionAndAmount is
|
||||
* nsIEditor::ePrevious, aHTElement is removed only when caret is at next
|
||||
* sibling of the `<hr>` element and inter line position is "left".
|
||||
* Otherwise, caret is moved and does not remove the `<hr>` element.
|
||||
* XXX Perhaps, we can get rid of this special handling because the other
|
||||
* browsers don't do this, and our `<hr>` element handling is really
|
||||
* odd.
|
||||
*
|
||||
* @param aDirectionAndAmount Direction of the deletion.
|
||||
* @param aHRElement The `<hr>` element to be removed.
|
||||
* @param aCaretPoint The caret point (i.e., selection start or
|
||||
* end).
|
||||
* @param aWSRunScannerAtCaret WSRunScanner instance which was initialized
|
||||
* with the caret point.
|
||||
* @param aEditingHost The editing host.
|
||||
*/
|
||||
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult>
|
||||
HandleDeleteHRElement(HTMLEditor& aHTMLEditor,
|
||||
nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint,
|
||||
const WSRunScanner& aWSRunScannerAtCaret,
|
||||
const Element& aEditingHost);
|
||||
nsresult ComputeRangesToDeleteHRElement(
|
||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint,
|
||||
const WSRunScanner& aWSRunScannerAtCaret,
|
||||
AutoRangeArray& aRangesToDelete) const;
|
||||
|
||||
/**
|
||||
* HandleDeleteAtOtherBlockBoundary() handles deletion at other block boundary
|
||||
* (i.e., immediately before or after a block). If this does not join blocks,
|
||||
@ -376,14 +346,6 @@ class MOZ_STACK_CLASS HTMLEditor::AutoDeleteRangesHandler final {
|
||||
GetRangeToAvoidDeletingAllListItemsIfSelectingAllOverListElements(
|
||||
const EditorRawDOMRange& aRangeToDelete);
|
||||
|
||||
/**
|
||||
* ShouldDeleteHRElement() checks whether aHRElement should be deleted
|
||||
* when selection is collapsed at aCaretPoint.
|
||||
*/
|
||||
Result<bool, nsresult> ShouldDeleteHRElement(
|
||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint) const;
|
||||
|
||||
/**
|
||||
* DeleteUnnecessaryNodes() removes unnecessary nodes around aRange.
|
||||
* Note that aRange is tracked with AutoTrackDOMRange.
|
||||
@ -1772,6 +1734,7 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteAroundCollapsedRanges(
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedSpecialContent() ||
|
||||
aScanFromCaretPointResult.ReachedBRElement() ||
|
||||
aScanFromCaretPointResult.ReachedHRElement() ||
|
||||
aScanFromCaretPointResult.ReachedNonEditableOtherBlockElement()) {
|
||||
if (aScanFromCaretPointResult.GetContent() ==
|
||||
aWSRunScannerAtCaret.GetEditingHost()) {
|
||||
@ -1793,22 +1756,6 @@ HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteAroundCollapsedRanges(
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedHRElement()) {
|
||||
if (aScanFromCaretPointResult.GetContent() ==
|
||||
aWSRunScannerAtCaret.GetEditingHost()) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv =
|
||||
ComputeRangesToDeleteHRElement(aHTMLEditor, aDirectionAndAmount,
|
||||
*aScanFromCaretPointResult.ElementPtr(),
|
||||
aWSRunScannerAtCaret.ScanStartRef(),
|
||||
aWSRunScannerAtCaret, aRangesToDelete);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"AutoDeleteRangesHandler::ComputeRangesToDeleteHRElement() failed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedOtherBlockElement()) {
|
||||
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -1953,9 +1900,9 @@ HTMLEditor::AutoDeleteRangesHandler::HandleDeleteAroundCollapsedRanges(
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedSpecialContent() ||
|
||||
aScanFromCaretPointResult.ReachedBRElement() ||
|
||||
aScanFromCaretPointResult.ReachedHRElement() ||
|
||||
aScanFromCaretPointResult.ReachedNonEditableOtherBlockElement()) {
|
||||
if (aScanFromCaretPointResult.GetContent() ==
|
||||
aWSRunScannerAtCaret.GetEditingHost()) {
|
||||
if (aScanFromCaretPointResult.GetContent() == &aEditingHost) {
|
||||
return EditActionResult::HandledResult();
|
||||
}
|
||||
nsCOMPtr<nsIContent> atomicContent = GetAtomicContentToDelete(
|
||||
@ -1985,31 +1932,6 @@ HTMLEditor::AutoDeleteRangesHandler::HandleDeleteAroundCollapsedRanges(
|
||||
return EditActionResult::HandledResult();
|
||||
}
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedHRElement()) {
|
||||
if (aScanFromCaretPointResult.GetContent() == &aEditingHost) {
|
||||
return EditActionResult::HandledResult();
|
||||
}
|
||||
Result<CaretPoint, nsresult> caretPointOrError = HandleDeleteHRElement(
|
||||
aHTMLEditor, aDirectionAndAmount,
|
||||
MOZ_KnownLive(*aScanFromCaretPointResult.ElementPtr()),
|
||||
aWSRunScannerAtCaret.ScanStartRef(), aWSRunScannerAtCaret,
|
||||
aEditingHost);
|
||||
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
|
||||
NS_WARNING("AutoDeleteRangesHandler::HandleDeleteHRElement() failed");
|
||||
return caretPointOrError.propagateErr();
|
||||
}
|
||||
nsresult rv = caretPointOrError.unwrap().SuggestCaretPointTo(
|
||||
aHTMLEditor, {SuggestCaret::OnlyIfHasSuggestion});
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CaretPoint::SuggestCaretPointTo() failed");
|
||||
return Err(rv);
|
||||
}
|
||||
NS_WARNING_ASSERTION(
|
||||
rv != NS_SUCCESS_EDITOR_BUT_IGNORED_TRIVIAL_ERROR,
|
||||
"CaretPoint::SuggestCaretPointTo() failed, but ignored");
|
||||
return EditActionResult::HandledResult();
|
||||
}
|
||||
|
||||
if (aScanFromCaretPointResult.ReachedOtherBlockElement()) {
|
||||
if (NS_WARN_IF(!aScanFromCaretPointResult.GetContent()->IsElement())) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
@ -2349,164 +2271,6 @@ Result<CaretPoint, nsresult> HTMLEditor::AutoDeleteRangesHandler::
|
||||
return CaretPoint(std::move(pointToPutCaret));
|
||||
}
|
||||
|
||||
Result<bool, nsresult>
|
||||
HTMLEditor::AutoDeleteRangesHandler::ShouldDeleteHRElement(
|
||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint) const {
|
||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||
|
||||
if (StaticPrefs::editor_hr_element_allow_to_delete_from_following_line()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aDirectionAndAmount != nsIEditor::ePrevious) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only if the caret is positioned at the end-of-hr-line position, we
|
||||
// want to delete the <hr>.
|
||||
//
|
||||
// In other words, we only want to delete, if our selection position
|
||||
// (indicated by aCaretPoint) is the position directly
|
||||
// after the <hr>, on the same line as the <hr>.
|
||||
//
|
||||
// To detect this case we check:
|
||||
// aCaretPoint's container == parent of `<hr>` element
|
||||
// and
|
||||
// aCaretPoint's offset -1 == `<hr>` element offset
|
||||
// and
|
||||
// interline position is false (left)
|
||||
//
|
||||
// In any other case we set the position to aCaretPoint's container -1
|
||||
// and interlineposition to false, only moving the caret to the
|
||||
// end-of-hr-line position.
|
||||
EditorRawDOMPoint atHRElement(&aHRElement);
|
||||
|
||||
const InterlinePosition interlinePosition =
|
||||
aHTMLEditor.SelectionRef().GetInterlinePosition();
|
||||
if (MOZ_UNLIKELY(interlinePosition == InterlinePosition::Undefined)) {
|
||||
NS_WARNING("Selection::GetInterlinePosition() failed");
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
return interlinePosition == InterlinePosition::EndOfLine &&
|
||||
aCaretPoint.GetContainer() == atHRElement.GetContainer() &&
|
||||
aCaretPoint.Offset() - 1 == atHRElement.Offset();
|
||||
}
|
||||
|
||||
nsresult HTMLEditor::AutoDeleteRangesHandler::ComputeRangesToDeleteHRElement(
|
||||
const HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint,
|
||||
const WSRunScanner& aWSRunScannerAtCaret,
|
||||
AutoRangeArray& aRangesToDelete) const {
|
||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(aHRElement.IsHTMLElement(nsGkAtoms::hr));
|
||||
MOZ_ASSERT(&aHRElement != aWSRunScannerAtCaret.GetEditingHost());
|
||||
|
||||
Result<bool, nsresult> canDeleteHRElement = ShouldDeleteHRElement(
|
||||
aHTMLEditor, aDirectionAndAmount, aHRElement, aCaretPoint);
|
||||
if (canDeleteHRElement.isErr()) {
|
||||
NS_WARNING("AutoDeleteRangesHandler::ShouldDeleteHRElement() failed");
|
||||
return canDeleteHRElement.unwrapErr();
|
||||
}
|
||||
if (canDeleteHRElement.inspect()) {
|
||||
nsresult rv = ComputeRangesToDeleteAtomicContent(
|
||||
aWSRunScannerAtCaret.GetEditingHost(), aHRElement, aRangesToDelete);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"AutoDeleteRangesHandler::ComputeRangesToDeleteAtomicContent() failed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
WSScanResult forwardScanFromCaretResult =
|
||||
aWSRunScannerAtCaret.ScanNextVisibleNodeOrBlockBoundaryFrom(aCaretPoint);
|
||||
if (forwardScanFromCaretResult.Failed()) {
|
||||
NS_WARNING("WSRunScanner::ScanNextVisibleNodeOrBlockBoundaryFrom() failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!forwardScanFromCaretResult.ReachedBRElement()) {
|
||||
// Restore original caret position if we won't delete anyting.
|
||||
nsresult rv = aRangesToDelete.Collapse(aCaretPoint);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AutoRangeArray::Collapse() failed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If we'll just move caret position, but if it's followed by a `<br>`
|
||||
// element, we'll delete it.
|
||||
nsresult rv = ComputeRangesToDeleteAtomicContent(
|
||||
aWSRunScannerAtCaret.GetEditingHost(),
|
||||
*forwardScanFromCaretResult.ElementPtr(), aRangesToDelete);
|
||||
NS_WARNING_ASSERTION(
|
||||
NS_SUCCEEDED(rv),
|
||||
"AutoDeleteRangesHandler::ComputeRangesToDeleteAtomicContent() failed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
Result<CaretPoint, nsresult>
|
||||
HTMLEditor::AutoDeleteRangesHandler::HandleDeleteHRElement(
|
||||
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount,
|
||||
Element& aHRElement, const EditorDOMPoint& aCaretPoint,
|
||||
const WSRunScanner& aWSRunScannerAtCaret, const Element& aEditingHost) {
|
||||
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(aHRElement.IsHTMLElement(nsGkAtoms::hr));
|
||||
MOZ_ASSERT(&aHRElement != aWSRunScannerAtCaret.GetEditingHost());
|
||||
|
||||
Result<bool, nsresult> canDeleteHRElement = ShouldDeleteHRElement(
|
||||
aHTMLEditor, aDirectionAndAmount, aHRElement, aCaretPoint);
|
||||
if (MOZ_UNLIKELY(canDeleteHRElement.isErr())) {
|
||||
NS_WARNING("AutoDeleteRangesHandler::ShouldDeleteHRElement() failed");
|
||||
return canDeleteHRElement.propagateErr();
|
||||
}
|
||||
if (canDeleteHRElement.inspect()) {
|
||||
Result<CaretPoint, nsresult> caretPointOrError =
|
||||
HandleDeleteAtomicContent(aHTMLEditor, aHRElement, aCaretPoint,
|
||||
aWSRunScannerAtCaret, aEditingHost);
|
||||
NS_WARNING_ASSERTION(
|
||||
caretPointOrError.isOk(),
|
||||
"AutoDeleteRangesHandler::HandleDeleteAtomicContent() failed");
|
||||
return caretPointOrError;
|
||||
}
|
||||
|
||||
// Go to the position after the <hr>, but to the end of the <hr> line
|
||||
// by setting the interline position to left.
|
||||
// There is one exception to the move only case. If the <hr> is
|
||||
// followed by a <br> we want to delete the <br>.
|
||||
WSScanResult forwardScanFromCaretResult =
|
||||
aWSRunScannerAtCaret.ScanNextVisibleNodeOrBlockBoundaryFrom(aCaretPoint);
|
||||
if (MOZ_UNLIKELY(forwardScanFromCaretResult.Failed())) {
|
||||
NS_WARNING("WSRunScanner::ScanNextVisibleNodeOrBlockBoundaryFrom() failed");
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
EditorDOMPoint pointToPutCaret(EditorDOMPoint::After(aHRElement));
|
||||
pointToPutCaret.SetInterlinePosition(InterlinePosition::EndOfLine);
|
||||
aHTMLEditor.TopLevelEditSubActionDataRef().mDidExplicitlySetInterLine = true;
|
||||
if (!forwardScanFromCaretResult.ReachedBRElement()) {
|
||||
return CaretPoint(std::move(pointToPutCaret));
|
||||
}
|
||||
|
||||
// Delete the <br>
|
||||
AutoTrackDOMPoint trackPointToPutCaret(aHTMLEditor.RangeUpdaterRef(),
|
||||
&pointToPutCaret);
|
||||
Result<CaretPoint, nsresult> caretPointOrError =
|
||||
WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt(
|
||||
aHTMLEditor,
|
||||
MOZ_KnownLive(*forwardScanFromCaretResult.BRElementPtr()),
|
||||
aCaretPoint, aEditingHost);
|
||||
if (MOZ_UNLIKELY(caretPointOrError.isErr())) {
|
||||
NS_WARNING(
|
||||
"WhiteSpaceVisibilityKeeper::DeleteContentNodeAndJoinTextNodesAroundIt("
|
||||
") failed");
|
||||
return caretPointOrError.propagateErr();
|
||||
}
|
||||
trackPointToPutCaret.FlushAndStopTracking();
|
||||
caretPointOrError.unwrap().MoveCaretPointTo(
|
||||
pointToPutCaret, aHTMLEditor,
|
||||
{SuggestCaret::OnlyIfHasSuggestion,
|
||||
SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
|
||||
return CaretPoint(std::move(pointToPutCaret));
|
||||
}
|
||||
|
||||
// static
|
||||
nsIContent* HTMLEditor::AutoDeleteRangesHandler::GetAtomicContentToDelete(
|
||||
nsIEditor::EDirection aDirectionAndAmount,
|
||||
|
@ -4840,15 +4840,6 @@
|
||||
value: "#FFFFFF"
|
||||
mirror: never
|
||||
|
||||
# Allow or disallow to delete `<hr>` element when caret is at start of
|
||||
# following line of the element. If false, Backspace from start of following
|
||||
# line of an `<hr>` element causes moving caret to immediatly after the `<hr>`
|
||||
# element, and then, another Backspace can delete it.
|
||||
- name: editor.hr_element.allow_to_delete_from_following_line
|
||||
type: bool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether editor initializes attributes and/or child nodes of newly inserting
|
||||
# element before or after connecting to the DOM tree.
|
||||
- name: editor.initialize_element_before_connect
|
||||
|
Loading…
Reference in New Issue
Block a user