Bug 1574852 - part 93: Move `HTMLEditRules::CheckInterlinePosition()` to `HTMLEditor` r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D44797

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2019-09-11 01:07:27 +00:00
Родитель 2fb41871a9
Коммит e3bcdb2d3c
3 изменённых файлов: 60 добавлений и 45 удалений

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

@ -707,8 +707,9 @@ nsresult HTMLEditRules::AfterEditInner() {
// adjust selection HINT if needed // adjust selection HINT if needed
if (!HTMLEditorRef() if (!HTMLEditorRef()
.TopLevelEditSubActionDataRef() .TopLevelEditSubActionDataRef()
.mDidExplicitlySetInterLine) { .mDidExplicitlySetInterLine &&
CheckInterlinePosition(); SelectionRefPtr()->IsCollapsed()) {
HTMLEditorRef().SetSelectionInterlinePosition();
} }
return NS_OK; return NS_OK;
@ -9666,13 +9667,9 @@ nsresult HTMLEditRules::PinSelectionToNewBlock() {
return NS_OK; return NS_OK;
} }
void HTMLEditRules::CheckInterlinePosition() { void HTMLEditor::SetSelectionInterlinePosition() {
MOZ_ASSERT(IsEditorDataAvailable()); MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(SelectionRefPtr()->IsCollapsed());
// If the selection isn't collapsed, do nothing.
if (!SelectionRefPtr()->IsCollapsed()) {
return;
}
// Get the (collapsed) selection location // Get the (collapsed) selection location
nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0); nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
@ -9680,50 +9677,63 @@ void HTMLEditRules::CheckInterlinePosition() {
return; return;
} }
EditorDOMPoint atStartOfSelection(firstRange->StartRef()); EditorDOMPoint atCaret(firstRange->StartRef());
if (NS_WARN_IF(!atStartOfSelection.IsSet())) { if (NS_WARN_IF(!atCaret.IsSet())) {
return; return;
} }
MOZ_ASSERT(atStartOfSelection.IsSetAndValid()); MOZ_ASSERT(atCaret.IsSetAndValid());
// First, let's check to see if we are after a <br>. We take care of this // First, let's check to see if we are after a `<br>`. We take care of this
// special-case first so that we don't accidentally fall through into one of // special-case first so that we don't accidentally fall through into one of
// the other conditionals. // the other conditionals.
nsCOMPtr<nsIContent> node = // XXX Although I don't understand "interline position", if caret is
HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(atStartOfSelection); // immediately after non-editable contents, but previous editable
if (node && node->IsHTMLElement(nsGkAtoms::br)) { // content is `<br>`, does this do right thing?
if (nsIContent* previousEditableContentInBlock =
GetPreviousEditableHTMLNodeInBlock(atCaret)) {
if (previousEditableContentInBlock->IsHTMLElement(nsGkAtoms::br)) {
IgnoredErrorResult ignoredError; IgnoredErrorResult ignoredError;
SelectionRefPtr()->SetInterlinePosition(true, ignoredError); SelectionRefPtr()->SetInterlinePosition(true, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(), NS_WARNING_ASSERTION(
"Failed to set interline position"); !ignoredError.Failed(),
"Selection::SetInterlinePosition(true) failed, but ignored");
return;
}
}
if (!atCaret.GetChild()) {
return; return;
} }
// Are we after a block? If so try set caret to following content // If caret is immediately after a block, set interline position to "right".
if (atStartOfSelection.GetChild()) { // XXX Although I don't understand "interline position", if caret is
node = HTMLEditorRef().GetPriorHTMLSibling(atStartOfSelection.GetChild()); // immediately after non-editable contents, but previous editable
} else { // content is a block, does this do right thing?
node = nullptr; if (nsIContent* previousEditableContentInBlockAtCaret =
} GetPriorHTMLSibling(atCaret.GetChild())) {
if (node && HTMLEditor::NodeIsBlockStatic(*node)) { if (HTMLEditor::NodeIsBlockStatic(*previousEditableContentInBlockAtCaret)) {
IgnoredErrorResult ignoredError; IgnoredErrorResult ignoredError;
SelectionRefPtr()->SetInterlinePosition(true, ignoredError); SelectionRefPtr()->SetInterlinePosition(true, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(), NS_WARNING_ASSERTION(
"Failed to set interline position"); !ignoredError.Failed(),
"Selection::SetInterlinePosition(true) failed, but ignored");
return; return;
} }
// Are we before a block? If so try set caret to prior content
if (atStartOfSelection.GetChild()) {
node = HTMLEditorRef().GetNextHTMLSibling(atStartOfSelection.GetChild());
} else {
node = nullptr;
} }
if (node && HTMLEditor::NodeIsBlockStatic(*node)) {
// If caret is immediately before a block, set interline position to "left".
// XXX Although I don't understand "interline position", if caret is
// immediately before non-editable contents, but next editable
// content is a block, does this do right thing?
if (nsIContent* nextEditableContentInBlockAtCaret =
GetNextHTMLSibling(atCaret.GetChild())) {
if (HTMLEditor::NodeIsBlockStatic(*nextEditableContentInBlockAtCaret)) {
IgnoredErrorResult ignoredError; IgnoredErrorResult ignoredError;
SelectionRefPtr()->SetInterlinePosition(false, ignoredError); SelectionRefPtr()->SetInterlinePosition(false, ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(), NS_WARNING_ASSERTION(
"Failed to unset interline position"); !ignoredError.Failed(),
"Selection::SetInterlinePosition(false) failed, but ignored");
}
} }
} }

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

@ -198,8 +198,6 @@ class HTMLEditRules : public TextEditRules {
*/ */
MOZ_MUST_USE nsresult PinSelectionToNewBlock(); MOZ_MUST_USE nsresult PinSelectionToNewBlock();
void CheckInterlinePosition();
/** /**
* DocumentModifiedWorker() is called by DocumentModified() either * DocumentModifiedWorker() is called by DocumentModified() either
* synchronously or asynchronously. * synchronously or asynchronously.

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

@ -2633,6 +2633,13 @@ class HTMLEditor final : public TextEditor,
*/ */
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult RemoveEmptyNodesIn(nsRange& aRange); MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult RemoveEmptyNodesIn(nsRange& aRange);
/**
* SetSelectionInterlinePosition() may set interline position if caret is
* positioned around `<br>` or block boundary. Don't call this when
* `Selection` is not collapsed.
*/
void SetSelectionInterlinePosition();
protected: // Called by helper classes. protected: // Called by helper classes.
virtual void OnStartToHandleTopLevelEditSubAction( virtual void OnStartToHandleTopLevelEditSubAction(
EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override; EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;