As the comment in the method, `CurrentBlockBoundary` may be set when `mContent`
is not a block. However, it's not allowed that there is an editable block
ancestor of `mContent` in same editing host (in this case, `mContent` should be
the block). Therefore, it should compute ancestor block element and check
whether it's not in same editing host if `mContent` is editable and connected.
Differential Revision: https://phabricator.services.mozilla.com/D190644
Sorry this is not a particularly easy patch to review. But it should be
mostly straight-forward.
I kept Document::Dispatch mostly for convenience, but could be
cleaned-up too / changed by SchedulerGroup::Dispatch. Similarly maybe
that can just be NS_DispatchToMainThread if we add an NS_IsMainThread
check there or something (to preserve shutdown semantics).
Differential Revision: https://phabricator.services.mozilla.com/D190450
This patch is related to Bug 1840822, which fixes some issues
regarding additional invisible linebreaks needed at the end of
contenteditables.
This patch in particular fixes the case where the user
presses enter at the end of a pre-formatted
contenteditable, e.g.:
```
<span contenteditable style="display:block;white-space:pre-line">[]</span>
```
Prior to this patch, only one `<br>` was added,
the invisible padding linebreak was missing.
With this patch applied, the behaviour should be as expected:
```
<span contenteditable style="display:block;white-space:pre-line">\n<br></span>
```
Differential Revision: https://phabricator.services.mozilla.com/D190217
The other browsers move focus and `Selection` whe right click even if the
clicked element is not editable and even if there is a non-collapsed selection.
Fortunately, we already have similar code for the middle button press.
Therefore, we can make it run when the pressed button is the secondary button.
This also fixes bug 416546 and does not resurrect bug 709476.
However, this patch adds 2 prefs for making users customizable. Our traditional
behavior is, we never collapse non-collapses selection with a right click even
if clicked outside the selection. This allows users to open context menu for
selected text much easier. Therefore, even though the behavior is different
from the others, we should keep the traditional behavior, but some users may
want the other browsers' behavior instead. For them, this should be switchable
by a pref.
Additionally, I'm still not sure collapsing selection with a right click in
non-editable content especially for users using the caret browsing mode.
Therefore, for making things safer, this adds a pref to disable the new behavior
in the non-editable content.
Differential Revision: https://phabricator.services.mozilla.com/D189991
If `HTMLEditor::HandleInsertBRElement` inserts an invisible `<br>` element
after a `<br>` element which is requested, new caret position should be
at the invisible `<br>` element.
Differential Revision: https://phabricator.services.mozilla.com/D189997
Without this patch, the following test newly fails:
```
/editing/other/insertparagraph-with-white-space-style.tentative.html?white-space=nowrap&command=insertText
FAIL <div contenteditable style="white-space:nowrap; display:inline">abc[]</div> (defaultparagraphseparator: div) - assert_equals: A <br> should be inserted at end expected "abc<br><br>" but got "abc<br>"
FAIL <div contenteditable style="white-space:nowrap; display:inline">abc[]</div> (defaultparagraphseparator: p) - assert_equals: A <br> should be inserted at end expected "abc<br><br>" but got "abc<br>"
```
The reasons is, the inlined editing host is at end of the `<body>`, therefore,
even though the editing host itself is `inline`, it needs a padding `<br>` to
make it the new line visible.
However, `HTMLEditUtils::GetElementOfImmediateBlockBoundary` does not return
`<body>` because the editing host is followed by `<script>` which has
a text node which is not white-spaces only. Therefore,
`HTMLEditUtils::IsVisibleBRElement` considers the `<br>` element at end of the
editing host is "visible".
Differential Revision: https://phabricator.services.mozilla.com/D188599
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
This didn't work properly for non-native key bindings because:
https://hg.mozilla.org/mozilla-central/rev/8934e6e6ccb6
Moved the DetachedFromEditorOrDefaultPrevented() check before the "hide
cursor" check, rather than after. This was a quick fix, because if we're
detached from the editor, then GetPresContext would assert. But I didn't
realize at the time (since it was a long time since I wrote the patch)
that most events there actually are default-prevented.
To fix this, split the checks. Checks for DetachedFromEditor() first,
and only after potentially hiding the cursor check whether the event is
default-prevented.
Differential Revision: https://phabricator.services.mozilla.com/D187536
The new join/split node direction mode seems working well in the wild because
we have no regression reports about it. Therefore, we won't revert the pref
anymore, thus, the legacy mode behavior check is not required.
Differential Revision: https://phabricator.services.mozilla.com/D186680
It returns the result of
`MakeSureToKeepVisibleStateOfWhiteSpacesAroundDeletingRange()`, but it suggests
caret position only when it modifies the DOM tree since it does not take the
default caret position.
So, `DeleteContentNodeAndJoinTextNodesAroundIt()` does need to return
`aCaretPoint` with tracking it during DOM mutations if
`MakeSureToKeepVisibleStateOfWhiteSpacesAroundDeletingRange()` does not
suggest caret point.
I found this bug when I was trying to fix the unexpected failing of
forward delete at end of the last block in the editing host (bug 1850666)
because changing the error handling anyway cause another error at this line.
https://searchfox.org/mozilla-central/rev/bdd5b85b56885cd48bd91d262647e0d3499b3a27/editor/libeditor/HTMLEditorDeleteHandler.cpp#1652
Therefore, without fixing bug 1850666, I have no idea how to check this fix.
Differential Revision: https://phabricator.services.mozilla.com/D187196
This only hides the cursor if it's on the page you're editing, but given
that the point of the feature is to move the cursor out of the way, that
seems acceptable (and honestly it feels more of a feature than a bug).
This should work across platforms (though non-windows platforms need
ui.hideCursorWhileTyping=1 in about:config to enable).
Differential Revision: https://phabricator.services.mozilla.com/D171155
This one is tricky because form controls, though I think I got it right...
This fixes a pre-existing bug where we're not following the spec for readonly
inside content-editable.
I filed this as bug 1850390 but other browsers match the spec so add a test and
fix it while at it. This allows cheaper checks for readonlyness in a couple
places.
Differential Revision: https://phabricator.services.mozilla.com/D186896
It does nothing in most cases because it inserts a `<br>` element only when
the editable `<body>` does not have meaningful content. Therefore, we can
make it put off to create `AutoEditSubActionNotifier` to save the cost of
some expensive things done by `OnStartToHandleTopLevelEditSubAction()` and
`OnEndHandlingTopLevelEditSubAction()`.
Differential Revision: https://phabricator.services.mozilla.com/D186514
A lone surrogate should not appear in `DOMString` at least when the attribute
values of events because of ill-formed UTF-16 string.
`TextEventDispatcher` does not handle surrogate pairs correctly. It should not
split surrogate pairs when it sets `KeyboardEvent.key` value for avoiding the
problem in some DOM API wrappers, e.g., Rust-running-as-wasm.
On the other hand, `.charCode` is an unsigned long attribute and web apps
may use `String.fromCharCode(event.charCode)` to convert the input to string,
and unfortunately, `fromCharCode` does not support Unicode character code
points over `0xFFFF`. Therefore, we may need to keep dispatching 2 `keypress`
events per surrogate pair for the backward compatibility.
Therefore, this patch creates 2 prefs. One is for using single-keypress
event model and double-keypress event model. The other is for the latter,
whether `.key` value never has ill-formed UTF-16 or it's allowed.
If using the single-keypress event model --this is compatible with Safari and
Chrome in non-Windows platforms--, one `keypress` event is dispatched for
typing a surrogate pair. Then, its `.charCode` is over `0xFFFF` which can
work with `String.fromCodePoint()` instead of `String.fromCharCode()` and
`.key` value is set to simply the surrogate pair (i.e., its length is 2).
If using the double-keypress event model and disallowing ill-formed UTF-16
--this is the new default behavior for both avoiding ill-formed UTF-16 string
creation and keeping backward compatibility with not-maintained web apps using
`String.fromCharCode`--, 2 `keypress` events are dispatched. `.charCode` for
first one is the code of the high-surrogate, but `.key` is the surrogate pair.
Then, `.charCode` for second one is the low-surrogate and `.key` is empty
string. In this mode, `TextEditor` and `HTMLEditor` ignores the second
`keypress`. Therefore, web apps can cancel it only with the first `keypress`,
but it indicates the `keypress` introduces a surrogate pair with `.key`
attribute.
Otherwise, if using the double-keypress event model and allowing ill-formed
UTF-16 --this is the traditional our behavior and compatible with Chrome in
Windows--, 2 `keypress` events are dispatched with same `.charCode` values as
the previous mode, but first `.key` is the high-surrogate and the other's is
the low surrogate. Therefore, web apps can cancel either one of them or
both of them.
Finally, this patch makes `TextEditor` and `HTMLEditor` handle text input
with `keypress` events properly. Except in the last mode, `beforeinput` and
`input` events are fired once and their `data` values are the surrogate pair.
On the other hand, in the last mode, 2 sets of `beforeinput` and `input` are
fired and their `.data` values has only the surrogate so that ill-formed
UTF-16 values.
Note that this patch also fixes an issue on Windows. Windows may send a high
surrogate and a low surrogate with 2 sets of `WM_KEYDOWN` and `WM_KEYUP` whose
virtual keycode is `VK_PACKET` (typically, this occurs with `SendInput` API).
For handling this correctly, this patch changes `NativeKey` class to make it
just store the high surrogate for the first `WM_KEYDOWN` and `WM_KEYUP` and use
it when it'll receive another `WM_KEYDOWN` for a low surrogate.
Differential Revision: https://phabricator.services.mozilla.com/D182142
This patch deals with this case:
```
<span contenteditable><div>foo</div>[]</span>
```
In this case only one `<br>` should be added since one
line break is already added because of the `<div>` block.
Differential Revision: https://phabricator.services.mozilla.com/D185935
The logic behind this patch is similar to that of part 1, only that this covers the case where a user triggers a line break instead of a new paragraph (i.e. by pressing [Shift/cmd]+[Enter]).
If the inserted BR element is followed by a block boundary, another BR element is added.
Depends on D182339
Differential Revision: https://phabricator.services.mozilla.com/D182485
If a user presses <Enter> to add a new paragraph at the end of a contenteditable, a second (invisible) line break has to be added:
`<span contenteditable>foo[]</span>` --> `<span contenteditable>foo<br><br></span>`
This patch deals with contenteditables which do not preformat whitespaces
(i.e. should insert linebreaks, not linefeeds).
The linefeed cases are handled in Bug 1840856.
Also this patch only deals with a code path that uses `insertParagraph`.
The code path that uses `InsertLineBreak` is handled in part 2 of this Bug.
The patch implements a lambda function that inserts a second `<br>` element,
which is called in two situations:
1. The editing host is empty:
`<span contenteditable>[]</span>`--> `<span contenteditable><br><br></span>`
2. The caret is at a block boundary:
`<span contenteditable>abc[]</span>` --> `<span contenteditable>abc<br><br></span>`
Differential Revision: https://phabricator.services.mozilla.com/D182339
Calling `UpdateDefaultPreventedOnContent` separately from
`PreventDefault()` is error-prone. This patch should make it
safer.
Differential Revision: https://phabricator.services.mozilla.com/D186052
`ContentEventHandler` works with `PostContentIterator` and `PreContentIterator`
when it scans DOM nodes in a range. While iterating the DOM nodes, script
never runs. Therefore, we can make `ContentEventHandler` work with new
content iterators which do not store nodes with strong pointers.
This patch makes `ContentIteratorBase` a template class and create new
`UnsafePostContentIterator` and `UnsafePreContentIterator`. They will
check whether DOM mutation or GC occurs before destruction to detect dangerous
regressions.
Differential Revision: https://phabricator.services.mozilla.com/D184441
Implemented the new <search> HTML element.
All WPT tests for it now pass (except one for iso-8859-8, not done generally).
A11y role uses just landmark as recommended instead of a new search role (for now).
Co-authored-by: Henri Sivonen <hsivonen@mozilla.com>
Differential Revision: https://phabricator.services.mozilla.com/D176967
Using the test for bug 1602526 as the basis for the new test but tweaking it by
adding the event listener used in the first testcase of the bug.
Differential Revision: https://phabricator.services.mozilla.com/D184987
Due to the `DOMNodeRemoved` event listener, splitting at range boundaries
may fail tracking the DOM tree due to unexpected container lost. In the
cases, the method should abort its task.
Differential Revision: https://phabricator.services.mozilla.com/D184457
Some basic clean-up. I want to do this before doing bigger changes in
bug 1843044.
There's tons more code that can get cleaned-up on the widget side, but
let's start with this.
Differential Revision: https://phabricator.services.mozilla.com/D183622
Element.focus() now centers an element in the block and inline
directions when the element should be scrolled into view. Update tests
to account for this.
Differential Revision: https://phabricator.services.mozilla.com/D183541
This translation shows up prominently in the TipTap
Speedometer3 test. Chrome doesn't seem to do this translation
and other Windows programs also show inconsistency around
new lines.
Let's try disabling it on Nightly to check if anything breaks.
Differential Revision: https://phabricator.services.mozilla.com/D183046
Once a parent node is removed from the tree, the node may become not editable
because editable state "inherits" from ancestor nodes.
`HTMLEditor::ClearStyleAt` cleans up unnecessary parent inline elements first,
but if `<br>` element which should be reused in the block parent is contained
the inline elements, `HTMLEditUtils::IsRemovableNode()` will start returning
`false` for the `<br>` element because of in a document fragment which do not
contain an element whose `contenteditable` is `true`. Then,
`MoveNodeWithTransaction` fails to move it because of unremovable.
Therefore, this patch makes the method move `<br>` element before removing
inline elements and use `InsertNodeWithTransaction` instead if `<br>` element
is an orphan node.
Differential Revision: https://phabricator.services.mozilla.com/D182640
The EditorEventListener for HTMLEditor is registered on document,
which is problematic because it can't receive events when the focus is
switched between elements in the same shadow tree due to shadow dom
encapsulation.
We fix this by moving the EditorEventListener to nsWindowRoot so the
events can always be received.
Differential Revision: https://phabricator.services.mozilla.com/D178215
The logic behind this patch is similar to that of part 1, only that this covers the case where a user triggers a line break instead of a new paragraph (i.e. by pressing [Shift/cmd]+[Enter]).
If the inserted BR element is followed by a block boundary, another BR element is added.
Differential Revision: https://phabricator.services.mozilla.com/D182485
If a user presses <Enter> to add a new paragraph at the end of a contenteditable, a second (invisible) line break has to be added:
`<span contenteditable>foo[]</span>` --> `<span contenteditable>foo<br><br></span>`
This patch deals with contenteditables which do not preformat whitespaces
(i.e. should insert linebreaks, not linefeeds).
The linefeed cases are handled in Bug 1840856.
Also this patch only deals with a code path that uses `insertParagraph`.
The code path that uses `InsertLineBreak` is handled in part 2 of this Bug.
The patch implements a lambda function that inserts a second `<br>` element,
which is called in two situations:
1. The editing host is empty:
`<span contenteditable>[]</span>`--> `<span contenteditable><br><br></span>`
2. The caret is at a block boundary:
`<span contenteditable>abc[]</span>` --> `<span contenteditable>abc<br><br></span>`
Differential Revision: https://phabricator.services.mozilla.com/D182339
Before bug 1770874, `EditorBase::OnBlur` checked that for both `TextEditor`
and `HTMLEditor`. However, accidentally, I removed the check from `TextEditor`.
Therefore, a call of `EditorBase::FinalizeSelection()` will hide the caret
even after another editor gets focus.
Therefore, this patch just take it back into `TextEditor::OnBlur`.
Note that I don't think the design mode handling is required there because
`TextEditor`s shouldn't be created in the design mode document.
Differential Revision: https://phabricator.services.mozilla.com/D182468
Now, most users of `EditorBase::IsInPlaintextMode()` are `HTMLEditor` itself.
There are some exceptions:
`EditorBase::GetDesiredSpellCheckState()` uses it to consider whether the root
(`<body>` if `HTMLEditor`) element's `specllcheck` attribute should be referred
or document's editing state. I think that this should just check
`IsHTMLEditor()`, but I think it must be okay to keep this as-is for now.
`EditorEventListener::KeyUp()` uses it to consider whether `Ctrl` + left/right
`Shift` switches the text direction of the editing host if and only if user
installed both LTR/RTL keyboard layouts and running in Windows. I think that
this should keep working in plaintext mail composer because nobody can control
the direction in plaintext editor. Therefore, this needs to check either
`IsTextEditor()` or `IsPlaintextMailComposer()` returning `true`.
`EditorEventListener::DragEventHasSupportingData()` uses it to consider
whether the editor accepts styled text and files. Therefore, it needs to check
either `IsTextEditor()` or `IsPlaintextMailComposer()` returning `false`.
Finally, we can stop setting `nsIEditor::eEditorPlaintextMask` to `TextEditor`.
Differential Revision: https://phabricator.services.mozilla.com/D181866
It's used only by the mail composers. However, `EditorBase::mWrapColumn` is
also used by `TextEditor`. Therefore, `EditorBase` still needs to manage the
member, but the setters, `SetWrapColumn()` and `SetWrapWidth()` can be in
`TextEditor` and `HTMLEditor`.
Differential Revision: https://phabricator.services.mozilla.com/D181836
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
It was introduced in bug 206859, but the `<input type="text">` in
`<input type="file">` was replaced with `<label>` in bug 345195.
Additionally, it's used only by `EditorBase` to check `<input type="text">`
is in `<input type="file">`. Therefore, we don't need it anymore.
Differential Revision: https://phabricator.services.mozilla.com/D181599
We have more readable and faster versions (that just omit the namespace
arg).
Mostly done via sed, with a couple helpers to use the faster lookups
where possible.
Differential Revision: https://phabricator.services.mozilla.com/D181795
Instead, lazily schedule evaluation of them before styling, much like we
were doing for SVG.
A subtle tweak is that we only remain scheduled while in the document.
This allows us to use the "in document" bit plus the "mapped attributes
dirty" bit to know our scheduled status. It also prevents doing silly
work for disconnected elements, and having to do hashmap lookups on
adoption and node destruction.
Differential Revision: https://phabricator.services.mozilla.com/D181549
Instead, lazily schedule evaluation of them before styling, much like we
were doing for SVG.
A subtle tweak is that we only remain scheduled while in the document.
This allows us to use the "in document" bit plus the "mapped attributes
dirty" bit to know our scheduled status. It also prevents doing silly
work for disconnected elements, and having to do hashmap lookups on
adoption and node destruction.
Differential Revision: https://phabricator.services.mozilla.com/D181549
The EditorEventListener for HTMLEditor is registered on document,
which is problematic because it can't receive events when the focus is
switched between elements in the same shadow tree due to shadow dom
encapsulation.
We fix this by moving the EditorEventListener to nsWindowRoot so the
events can always be received.
Differential Revision: https://phabricator.services.mozilla.com/D178215
It should not meet such situation if only editor updates the DOM tree.
Therefore, the result should be cleared in that case and all users should return
`NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE` in this case.
Depends on D180785
Differential Revision: https://phabricator.services.mozilla.com/D180786
The assertion failure is caused by that `RemoveChild()` or `InsertBefore()` is
failed, and overriding the error code with `NS_ERROR_EDITOR_DESTROYED`.
For saving the construction cost of `ErrorResult` instances, the related methods
take `ErrorResult&` as in/out-param. However, the cost is not so high if we
use `IgnoredErrorResult` and do not create it in the `for` loop in
`MoveChildrenBetween()`. Therefore, this patch make them return `nsresult`
simply to avoid updating error code and suppressing JS error in various places.
Depends on D180786
Differential Revision: https://phabricator.services.mozilla.com/D180787
The assertion was introduced in bug 1655988. However, the assertion assumes
that the given range ends before start of the deleting range (invisible
white-spaces), but that is wrong, the range may ends in middle of or end of
collapsible white-spaces. Therefore, this patch just fixes the assertion.
Depends on D180783
Differential Revision: https://phabricator.services.mozilla.com/D180785
There are 2 possible scenarios which are not handled by the method.
1. Moving content node to new `<blockquote>` has already been moved to outside
of the editing host.
2. There is no container to insert new `<blockquote>`, e.g., in an inline
editing host.
In the case #1, we should ignore the ex-child node. In the case #2, we should
abort it. Note that Chrome inserts `<blockquote>` even if there is no proper
container. However, such behavior is disagreed in interop-2023. Therefore,
it's okay just to abort it for now.
Depends on D180781
Differential Revision: https://phabricator.services.mozilla.com/D180782
It may be called with `AutoTransactionsConserveSelection` instance.
Therefore, it may return `aPoint` as-is even after modifying the DOM tree.
So it should track the point during a call of
`SplitAncestorStyledInlineElementsAt()`.
Depends on D179421
Differential Revision: https://phabricator.services.mozilla.com/D179422
The `outdent` handler faces unexpected scenario due to the `<blockquote>`
element becomes not editable due to the `onstart` listener. The event listener
runs when the `<marquee>` moves from its container to new left node at splitting
it. Therefore, we need to put a lot of "removable node checks" before moving
nodes.
Differential Revision: https://phabricator.services.mozilla.com/D179421
In order to support `StaticRange`s, which are not `MutationObserver`s, RangeBoundaries need to have an alternative way of ensuring that `mRef` points to the correct node.
This is now done by validating `mRef` every time `Ref()` is called using the parent and offset.
For performance reasons, this is disabled by default and should only be used for `StaticRange`s.
Differential Revision: https://phabricator.services.mozilla.com/D177892
I was going to write an automated test but turns out that some of this
became much harder to test after bug 582459 :-(
Let me know if you want me to take a look at writing a browser test
(since I think otherwise we can't test this, we need to move focus
outside of the active tab).
Differential Revision: https://phabricator.services.mozilla.com/D178825
The EditorEventListener for HTMLEditor is registered on document,
which is problematic because it can't receive events when the focus is
switched between elements in the same shadow tree due to shadow dom
encapsulation.
We fix this by moving the EditorEventListener to nsWindowRoot so the
events can always be received.
Differential Revision: https://phabricator.services.mozilla.com/D178215
The EditorEventListener for HTMLEditor is registered on document,
which is problematic because it can't receive events when the focus is
switched between elements in the same shadow tree due to shadow dom
encapsulation.
We fix this by moving the EditorEventListener to nsWindowRoot so the
events can always be received.
Differential Revision: https://phabricator.services.mozilla.com/D178215
When `WSRunScanner::ScanNextVisibleNodeOrBlockBoundary` reaches a block
boundary, it may return `WSScanResult` without valid position value from
this path:
https://searchfox.org/mozilla-central/rev/11a4d97a7b5cdfa133f4bda4525649f651703018/editor/libeditor/WSRunObject.cpp#1777-1782
That happens if the reason is `WSType::CurrentBlockBoundary` or
`WSType::OtherBlockBoundary` even in usual cases.
If it's `WSType::CurrentBlockBoundary`, `TextFragmentDataAtStartRef().EndRef()`
may point in a text node in the block, but its `GetEndReasonContent()` returns
the block. I'm not sure whether this is intentional result. (I guess t's a
bug.)
If it's `WSType::OtherBlockBoundary`, `TextFragmentDataAtStartRef().EndRef()`
may point in the list item, but `GetEndReasonContent()` returns a child block.
Those scan result change needs to understand `TextFragmentData` behavior again,
but it's difficult as you know. Therefore, this fixes the caller side not to
use `WSScanResult::Point()` if it meets a block boundary since start of the
block boundary is a good place to put caret.
Differential Revision: https://phabricator.services.mozilla.com/D178281
With the preceding patch, comment nodes are also moved at deleting a block/line
boundary. However, this causes some WPT failures. Therefore, this adds an
option to the related methods.
Note that Chrome removes all comment nodes in moving nodes. However, I don't
have the motivation to do that because it requires additional cost and I have
no idea to improve the compatibility in usual web apps. So I believe that
doing it wastes the runtime performance unless we'd get a bug reports by the
difference.
Therefore, this patch does not update WPTs too.
Differential Revision: https://phabricator.services.mozilla.com/D176767
`HTMLEditUtils::CanNodeContain` does not handle comment nodes and cdata section
nodes (the latter one is available only in XHTML documents, it's treated as a
comment node in HTML documents).
When copying HTML from Word on Windows, that contains 2 comment nodes at
start of pasting body (which does not appear in clipboard viewer, so, Gecko
creates them somewhere) and that causes `HTMLEditUtils::CanNodeContain` returns
`false` for any parents. Therefore,
`HTMLEditor::InsertNodeIntoProperAncestorWithTransaction` returns error
and the pasting fails with odd state and unexpectedly split the list item in
`HTMLWithContextInserter::InsertContents`. Finally, undoing fails to do some
of them and causes destroying the editable nodes.
This patch makes `HTMLEditUtils::CanNodeContain` work with comment nodes
and cdata section nodes (the latter is treated as a comment node since there
is no "cdata" tag definition of `nsHTMLTag`) and
`HTMLEditor::InsertNodeIntoProperAncestorWithTransaction` just return
"not handled" result for some other types of nodes which cannot be inserted
in any elements.
Note that the result of pasting from Word is different from Chrome's result.
Chrome does not paste such comment nodes (but inserts comment nodes with
`insertHTML` command). For now, I don't want to work on fixing this
compatibility issue since comment nodes does not cause any known troubles.
Therefore, this patch does not contain WPT updates.
Differential Revision: https://phabricator.services.mozilla.com/D176766
Some handlers, e.g., `HTMLWithContextInserter` may want to skip post processing
after inserting new node instead of immediately stop handling the action.
Currently, `HTMLWithContextInserter` correctly ignores the cases only when
`NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE` is required. Therefore, making
`InsertNodeWithTransaction` return the error makes `HTMLWithContextInserter`
work correctly in tricky cases.
Differential Revision: https://phabricator.services.mozilla.com/D177446
If a `paste` event listener moves focus, Chrome makes new editor keep handling
the pasting. For the compatibility, we should follow it unless the new focused
element is in different document because user should allow to paste it
explicitly.
On the other hand, this just stops handling "cut" in same situation because
handling it requires to update clipboard without user's activation. Therefore,
the clipboard content and/or the new editor content may be lost from the users
point of view.
Note that `nsContentUtils::GetActiveEditor` may return `HTMLEditor` instance
when focused element does not have `TextEditor` even when non-editable element
has focus. Therefore, if it returns an `HTMLEditor`, we need to check whether
it's active in the DOM window with a call of `HTMEditor::IsActiveInDOMWindow`.
Differential Revision: https://phabricator.services.mozilla.com/D176741
This patch makes `EditorBase` implement them as non-virtual methods and
implement their first part. Then, they call new virtual methods to handle
paste and paste-as-quotation.
With this change, `TextEditor` starts to dispatch `paste` event when
paste-as-quotation. The new test checks it.
Differential Revision: https://phabricator.services.mozilla.com/D176739
It does not handle critical cases properly, and it uses an out-param.
We can rewrite it with `Result`. However, unfortunately,
`nsCopySupport::FireClipboardEvent` does not return error. Therefore,
the root callers still need to treat the error cases as "canceled".
Differential Revision: https://phabricator.services.mozilla.com/D176737
If a `paste` event listener moves focus, Chrome makes new editor keep handling
the pasting. For the compatibility, we should follow it unless the new focused
element is in different document because user should allow to paste it
explicitly.
On the other hand, this just stops handling "cut" in same situation because
handling it requires to update clipboard without user's activation. Therefore,
the clipboard content and/or the new editor content may be lost from the users
point of view.
Note that `nsContentUtils::GetActiveEditor` may return `HTMLEditor` instance
when focused element does not have `TextEditor` even when non-editable element
has focus. Therefore, if it returns an `HTMLEditor`, we need to check whether
it's active in the DOM window with a call of `HTMEditor::IsActiveInDOMWindow`.
Differential Revision: https://phabricator.services.mozilla.com/D176741
This patch makes `EditorBase` implement them as non-virtual methods and
implement their first part. Then, they call new virtual methods to handle
paste and paste-as-quotation.
With this change, `TextEditor` starts to dispatch `paste` event when
paste-as-quotation. The new test checks it.
Differential Revision: https://phabricator.services.mozilla.com/D176739
It does not handle critical cases properly, and it uses an out-param.
We can rewrite it with `Result`. However, unfortunately,
`nsCopySupport::FireClipboardEvent` does not return error. Therefore,
the root callers still need to treat the error cases as "canceled".
Differential Revision: https://phabricator.services.mozilla.com/D176737
`IMEStateManager` basically runs at focus change. However, when `designMode`
is set to `"off"` or focused editing host becomes non-editable (removing
`contenteditable` attribute or `contenteditable` attribute is set to `false`),
IME may be disabled without a focus change. Therefore, `Document` needs to
notify `IMEStateManager` of the timing.
Additionally, `nsFocusManager` does not change focus when focused element
becomes not focusable (bug 1807597). Therefore, `Document` needs to kick
`focus` or `blur` event handler of `HTMLEditor` when active editing host
becomes not editable.
However, if an ancestor of focused element becomes editable, I think that
`HTMLEditor` does not work well without focus move because it computes
editing host with current editing state in a lot of places, but `Selection`
and `nsFocusManager::GetFocusedElement` keeps working with previous focused
element which is now a editable child of editing host. Therefore, this patch
marks them as `todo` in the new tests.
Differential Revision: https://phabricator.services.mozilla.com/D171196
Make all UA widgets also NAC.
Keep the UA widget flag but break at anonymous subtree boundaries, so
that only nodes inside the UA widget directly (and not NAC from those)
get the flag.
This is important because two callers depend on this difference:
* The style system, since we still want to match content rules from
stylesheets in the UA widget. We also match user rules, which is a
bit sketchy, but that was the previous behavior, will file a
follow-up for that.
* The reflector code, since we want the scope for UA widgets to not
include the NAC nodes inside that UA widget. nsINode::IsInUAWidget
got it wrong.
After this patch, ChromeOnlyAccess is equivalent to
IsInNativeAnonymousSubtree, so we should probably unify the naming.
That's left for a follow-up patch because I don't have a strong
preference.
Differential Revision: https://phabricator.services.mozilla.com/D174310
This API is temporarily available and useful for web app developers who want to
stop supporting Gecko specific join/split direction handling as soon as possible
and who do not want Mozilla block their release schedule by rescheduling of
shipping the new behavior. Additionally, adding this command allows web apps
detects whether Gecko supports the new behavior and whether it's enabled.
On the other hand, We don't want to ship opt-out API because it's hard to keep
maintaining the legacy behavior specific paths. Therefore, the command does
nothing if web app calls
`Document.execCommand("enableCompatibleJoinSplitDirection", false "false")` if
the new behavior is enabled by default.
Differential Revision: https://phabricator.services.mozilla.com/D172351
The source node is typically a text node, and it may be editable by
`contenteditable` or `designMode`. In that case, the source node may be removed
during the DnD session even without tricky JS code. In this case, Blink and
WebKit updates the source node to dispatch `dragend` to the editing host.
This behavior does not conform to the standardized DnD behavior, however,
this is reasonable for editor apps which want to listen to events in editing
host or window/document for footprint and/or performance reason. Therefore,
we should follow their behavior.
Differential Revision: https://phabricator.services.mozilla.com/D172091
If one of them are removed from the DOM tree, it's hard to keep handling it
since we have both split direction paths. Therefore, let's just return error
but not throw new exception in the case.
Differential Revision: https://phabricator.services.mozilla.com/D172205
The root cause of this bug is, we tried to compute new offset with offset at
the new node. However, as explained in the inline comments, it should compute
the offset with the right node offset in the new mode. Therefore, it needs
to handle it by itself instead of just calling `SelAdjInsertNode`.
Differential Revision: https://phabricator.services.mozilla.com/D171965
In the legacy mode, right node is not removed from the DOM tree, therefore,
this bug was hidden. However, after enabling the new mode, the point will
be out of the document. Therefore, the check will cause
`NS_ERROR_EDITOR_UNEXPECTED_DOM_TREE` error and the joining code stops handling
the deletion.
Differential Revision: https://phabricator.services.mozilla.com/D171822
Computed color values will not be in the correct format, closer to the
one specified by the author. This also means that colors accross the
code are stored now as AbsoluteColor or StyleAbsoluteColor. This allows
color space/gamut information to be available for use.
Some animation related test failures had to be changed, because colors
now has greater precision. Animated a color now causes a lot more
animation updates, which was not initially expected. See the bug for
discussion.
Differential Revision: https://phabricator.services.mozilla.com/D171021
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
However, we still need to climbing up the tree when
`nsIFrame::GetPrimaryFrame()` returns `nullptr`.
`<span inert style="display:none">` cases fail in Chrome. It must be caused by
their editor's `Selection` normalization result, but I think that it's wrong
behavior because `Selection` is a DOM API and the range is `inert`ed element.
Therefore, it's odd to change the behavior from the style.
Differential Revision: https://phabricator.services.mozilla.com/D170164
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