Commit Graph
17 Commits
Author SHA1 Message Date
Masayuki Nakano 4b50a3b1fd Bug 1883562 - part 1: Make AutoBlockElementsJoiner work with one range r=m_kato
It and its helper class, `AutoInclusiveAncestorBlockElementsJoiner` work with
multiple ranges, but they handle special cases only with the first range.
That means that deleting content will be different if same structure is selected
with multiple ranges and that must be not expected by the users.

Differential Revision: https://phabricator.services.mozilla.com/D203853
2024-03-11 08:01:50 +00:00
Masayuki Nakano 897f6fc48e Bug 1870222 - part 1: Rename HTMLEditUtils::EmptyCheckOption::IgnoreEditableState with inverting the meaning r=m_kato
It means that "treat non-editable things as visible" when it's not set.
However, it's odd.  You must assume that if no option is set, `IsEmpty()` etc
should treat non-editable nodes as visible things.  Therefore, this renames it
to `TreatNonEditableContentAsVisible` and changing all callers of
`HTMLEditUtils::IsEmptyNode`, `HTMLEditUtils::IsEmptyInlineContainer`,
`HTMLEditUtils::IsEmptyBlockElement` and
`HTMLEditUtils::CollectEmptyInlineContainerDescendants`.  So, this does not
change any behavior.

Differential Revision: https://phabricator.services.mozilla.com/D196813
2023-12-25 12:54:06 +00:00
Masayuki Nakano 67366ed791 Bug 1868641 - Make AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete not cross flex-item and grid-item boundary r=m_kato
The text input of the multi-select combobox of Slack has the following
structure:
```
<div contenteditable style="display:flex">
  <span class="c-multi_select_input__space">&nbsp;</span>
  <span class="c-multi_select_input__filter_query">text which you typed</span>
  <span class="c-multi_select_input__space" contenteditable="false">&nbsp;<span>
</div>
```

When you do "Select All", they adjust selection to start from start of the
text container `<span>` (i.e., `.c-multi_select_input__filter_query`).
Then, typing new character deletes selection first.  At this time, in the
legacy mode, `AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete` does not
extend the deleting range because `<span>` is an inline element.  However,
in the new mode, it extends the range because the `<span>` is a block since
it's a flex-item, and selection starts from current block boundary.  Then,
deleting range starts before the text container.  Finally, Gecko removes the
text container and the following non-editable `<span>`. Therefore, typing text
will be inserted as a child of the flex container which is the editing host.
Finally, Slack restores the previous structure and collapse selection to end
of the text.

Currently, Chrome does same thing for normal blocks without flex/gird container.
However, doing i in `AutoDeleteRangesHandler::ExtendOrShrinkRangeToDelete`
causes a lot of regressions. Therefore, this patch tries to avoid only the bug
in Slack. (I think that we need to redesign the deletion handler to fix it.)

Differential Revision: https://phabricator.services.mozilla.com/D195955
2023-12-13 00:51:01 +00:00
Masayuki Nakano 387d5cb1ec Bug 1865729 - part 1: Make AutoMoveOneLineHandler make AutoRangeArray work with BlockInlineCheck::UseComputedDisplayOutsideStyle r=m_kato
`AutoMoveOneLineHandler` uses `AutoRangeArray` API for block level edit
sub-actions.  Therefore, the source line is computed with
`BlockInlineCheck::UseHTMLDefaultStyle`.  However, the deletion handler works
with `BlockInlineCheck::UseComputedDisplayOutsideStyle`.  Therefore,
`AutoMoveOneLineHandler` may try to move different range.  In the reported
test case, it tries to move all content under the `<body>` into the
`<a display="table-header-group">` which is contained in the range.  Therefore,
the `movedContentRange` check fails after the destination becomes into an
orphan node which was removed to move.

This patch renames the API and adds a `BlockInlineCheck` parameter to work
with both ways and makes `AutoMoveOneLineHandler` specify
`BlockInlineCheck::UseComputedDisplayOutsideStyle` as same as the other delete
handlers.

Finally, same thing may happen in
`HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal`.  This patch makes it
check whether the top-level edit sub-action is a block level one or not and
consider `BlockInlineCheck` with the result.

Depends on D194180

Differential Revision: https://phabricator.services.mozilla.com/D194181
2023-11-27 01:46:42 +00:00
Masayuki Nakano e8afcee76e Bug 1244437 - part 3: Make formatBlock command handlers use replace target as the nearest inclusive ancestor format node r=m_kato
Currently, we extend selection to outside block boundaries if selection starts
and/or ends very start/end of block boundaries.  Then, replace most-distant
ancestor format node, but this is odd because the innermost format is applied
to the text and the other browsers targets the innermost ancestor formant node.
Therefore, we should align to them.

Additionally, our replacing code for `<dd>` and `<dt>` has not been implemented
yet.  I guess that the old `HTMLEditUtils::IsFormatNode` returned `false` for
`<dd>`, `<dl>` and `<dt>` and it requires additional work for splitting parent
`<dl>` too.  Now, we can do it with simple code.

Finally, we created new format block element if `<br>` element appears, but
the other browsers moves it into the new format node simply.  Therefore, we
should follow them (about `<blockquote>`, we've already done this within
the different path).

Differential Revision: https://phabricator.services.mozilla.com/D190902
2023-10-26 03:45:18 +00:00
Masayuki Nakano 6f1b3be29e Bug 1851951 - Make HTMLEditor refer computed display instead of the HTML default style at considering block or inline element r=m_kato
Blink [1] and WebKit [2] refers `display-outside` value when they consider whether an
element is a block or an inline.

However, our editor refers HTML default style instead.  Therefore, our editor
cannot handle the following cases:
* If a container block is a non-HTML element whose `display` style is `block`.
* If a container `<div>` etc is styled as `inline` and typing `Enter` in it.
* If a container `<span>` is styled as `block` and it ends with spaces.

For making users get better result, we should follow the other browsers.

However, this is too risky change.  Therefore, this patch enables new behavior
only in the Nightly channel and early beta builds to collect feedback from
testers.

The big rules of checking block vs. inline are:
* When we handle block level edit actions such as formatting block, indenting
or outdenting selection, making or removing list, we should keep referring
the HTML default style because the other browsers do so and the commands are
intended for modifying the HTML structure.
* Otherwise, we should refer the computed style of the block.  However, if
working with non-connected elements, we may need a special handling that is
falling back to refer the HTML default style because `HTMLEditorDataTransfer`
work with non-connected document fragments.
* Finally, if we check visibility of collapsible white-spaces and `<br>`s, we
should refer computed style.  However, in this case, we may need to treat
ancestor `inline-block`s as block too, but for siblings, we should refer only
`display-outside`.

1. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/editing/editing_utilities.cc;l=779;drc=31fb07c05718d671d96c227855bfe97af9e3fb20
2. https://searchfox.org/wubkat/rev/b054636fffeffa0314914a11ce39725a3057131e/Source/WebCore/editing/Editing.cpp#317

Differential Revision: https://phabricator.services.mozilla.com/D188598
2023-09-27 03:01:26 +00:00
Masayuki Nakano f84a751fe1 Bug 1839793 - Move EditorBase::FindBetterInsertionPoint into TextEditor r=m_kato
Currently it runs if the instance is a `TextEditor` or it's in the plaintext
mode of `HTMLEditor`.  However, it does not make sense to run it only in
specific mode of `HTMLEditor`, and most part does not make sense for
`HTMLEditor`.

This patch moves the method to `TextEditor`, and for
`EditorBase::InsertTextWithTransaction()` and
`AutoRangeArray::ExtendAnchorFocusRangeFor()`, adds new method to
`EditorDOMPointBase` to get a text node position if it points around
a text node.

Differential Revision: https://phabricator.services.mozilla.com/D181835
2023-06-27 04:23:09 +00:00
Masayuki Nakano 103c0199cc Bug 1775380 - Clean up for-loops in AutoRangeArray with range-based for loops r=m_kato
Depends on D180782

Differential Revision: https://phabricator.services.mozilla.com/D180783
2023-06-15 08:15:38 +00:00
Masayuki Nakano 3016d82071 Bug 1818339 - Make AutoRangeArray set mAnchorFocusRange correctly r=m_kato
There are some paths which do not set `mAnchorFocusRange` correctly.
Therefore, even if its `RangeCount()` returns 1 or larger,
`GetAnchorFocusRange()` may return `nullptr`.

Differential Revision: https://phabricator.services.mozilla.com/D171045
2023-02-28 00:46:17 +00:00
Jan-Niklas Jaeschke 931523860e Bug 1810403: Allow nsRanges to be in multiple Selections. r=masayuki
The Custom Highlight API allows a use case where a `Range` of a `Highlight`
is also used as `Selection`. Due to the decision to use the `Selection` mechanism
to display `Highlight`s, a `Range` can be part of several `Selection`s.
Since the `Range` has a pointer to its associated `Selection`
to notify about changes, this must be adapted to allow several `Selections`.

As a tradeoff of performance and memory usage, the `Selection`s are stored
as `mozilla::LinkedList`. A helper class `mozilla::SelectionListWrapper`
was implemented to allow `Selection`s to be in multiple of these lists
and without having to be derived from `LinkedListElement<T>`.

To simplify usage of the list, the use case  "does this range belong to Selection x?"
is wrapped into the convenience method`IsInSelection(Selection&)`;
The method previously named like this was renamed to `IsInAnySelection()`
to be named more precisely.

Registering and unregistering of the closest common inclusive ancestor
of the `Range` is done when the first `Selection` is registered and
the last `Selection` is unregistered.

Differential Revision: https://phabricator.services.mozilla.com/D169597
2023-02-21 12:25:28 +00:00
Masayuki Nakano 706fa02c8f Bug 1816039 - Make HTMLEditor handle selection ranges which starts from or ends in <foo inert> r=m_kato
According to the WPTs and their result in the other browsers, we should:
* do not work with a range anchored from a node in an element which has `inert`.
* collapse the range first when it ends at a node in an element which has `inert`.

See new WPT for the detail.

Note that `inert` with `contenteditable` must not be so major cases.  Therefore,
this patch does not fix the edge cases like the `nsFrameSelection` use cases
and replacing `Selection` cases of the other edit commands/operations.

Depends on D169037

Differential Revision: https://phabricator.services.mozilla.com/D169743
2023-02-15 22:06:31 +00:00
Masayuki Nakano c88a513e45 Bug 1811409 - part 4: Make AutoMoveOneLineHandler never split container of insertion point r=m_kato
One of the crash reasons is, the destination is the parent `<video>` of the
`<ol>`.  When `AutoRangeArray` considers the range of first line is, making
`<video><source/>{<ol><li>a</li></ol>}`.  This is not intuitive, but extending
the range to outside of the block boundaries is required to collect editable
target nodes.  However, this causes a problem.  `AutoMoveOneLineHandler` splits
the parent `<video>` element at the range boundaries with
`AutoRangeArray::SplitTextNodesAtEndBoundariesAndParentInlineElementsAtBoundaries`
since it's treated as an inline element.  However, the `<video>` element is the
container of destination, so this is one unexpected issue for
`AutoMoveOneLineHandler`.  Then, it tries to move split empty nodes to same
or another `<video>` element (depending on the split node direction).  However,
at this time, it fails to move the node and delete it instead because `<video>`
cannot have not all elements.  If the source `<video>` and destination `<video>`
is same one, nodes disappear from `movedContentRange` in `Run()` and `Run()`
cannot track it.  Therefore, the range becomes invalid.

Ideal approach to fix this issue is, we should redesign considering where is
a line and how to collect the target nodes.   However, if I change the
`AutoRangeArray` methods to fix this case, a lot of regressions appeared because
they are shared in a lot of edit actions.  Therefore, I give up to fix them.

Instead, this patch just prevents to split the destination container.  This may
have not fixed the real point,  However, for now, we should just patch this
case because this could be potentially a problem for web apps which use inline
elements with `display: block`.

Differential Revision: https://phabricator.services.mozilla.com/D168183
2023-02-03 05:19:42 +00:00
Masayuki Nakano 0b074382f7 Bug 1793694 - part 3: Move definitions of JoinNodesDirection and SplitNodeDirection into a new exposed header file r=m_kato
They are used in public inline methods of `HTMLEditor`.  Therefore, they should
be defined in an exposed header file without other internal use things for the
editor module.  Then, we can stop exposing `HTMLEditHelpers.h`.

Depends on D158632

Differential Revision: https://phabricator.services.mozilla.com/D158633
2022-10-12 02:44:18 +00:00
Masayuki Nakano af5b2b3933 Bug 1792642 - Make SplitNodeResult treated as ok type of Result r=m_kato
Depends on D158333

Differential Revision: https://phabricator.services.mozilla.com/D158334
2022-10-04 07:28:10 +00:00
Masayuki Nakano 830bd376e2 Bug 1783402 - part 3: Make result of unsafe getter methods of EditorDOMPointBase templated r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D153842
2022-08-09 01:43:24 +00:00
Masayuki Nakano eb8aafe328 Bug 1783402 - part 2: Make result of safe getter methods of EditorDOMPointBase templated r=m_kato
Similar to the previous patch, and for consistency between editor helper
classes, we should make result of getter methods of `EditorDOMPointBase` too.

Differential Revision: https://phabricator.services.mozilla.com/D153841
2022-08-09 01:43:24 +00:00
Masayuki Nakano 276855fa75 Bug 1775381 - Move AutoRangeArray from EditorUtils.h to its own header and cpp file r=m_kato
Depends on D152982

Differential Revision: https://phabricator.services.mozilla.com/D153063
2022-08-04 05:39:16 +00:00