When using autocorrect, we should use `insertReplacementText` according
to https://github.com/w3c/input-events/issues/152. So I would like to
add eContentCommandReplaceText command for this.
Also, this command has an option that is source string text. When
processing text subsitution, parent process doesn't know whether
target replaced text is modified. So I add this option for check.
Differential Revision: https://phabricator.services.mozilla.com/D213511
Now, we have `nsFocusManager::GetFocusedElementStatic()` which returns focused
element if the `nsFocusManager` instance is available. Therefore, if
`nsFocusManager::GetFocusedElement()` users do not use other methods of
`nsFocusManager`, they can use `nsFocusManager::GetFocusedElementStatic()` and
make themselves simpler.
Note that some callers return early if `nsFocusManager` is not available, but
they do not return error and `nsFocusManager` instance is available in most
time of the life time of the process. Therefore, we can simply stop using the
early return.
Differential Revision: https://phabricator.services.mozilla.com/D217527
`HTMLEditor` currently checks whether it's in the `designMode` or not with
checking the `Document` node is in the `designMode`. I.e., it checks the
real-time state of the `Document` node. However, if an instance was in the
`designMode`, it needs to finalize `Selection` even after the `Document` node
becomes not in the `designMode`. Additionally, elements in a shadow DOM in the
`designMode` can have `contenteditable` to make it editable. Then, the editable
elements should works as in the `contenteditable` mode rather than in the
`designMode`. Therefore, current `HTMLEditor::IsInDesignMode()` returns
wrong state when the finalization is called asynchronously or when an editing
host in a shadow DOM whose composed document is in the `designMode`.
This patch fixes known cases of these issues with improving the finalization
(and re-initialization with the new editing mode) and the caller side in
`Document`.
Differential Revision: https://phabricator.services.mozilla.com/D216022
`HTMLEditor` currently checks whether it's in the `designMode` or not with
checking the `Document` node is in the `designMode`. I.e., it checks the
real-time state of the `Document` node. However, if an instance was in the
`designMode`, it needs to finalize `Selection` even after the `Document` node
becomes not in the `designMode`. Additionally, elements in a shadow DOM in the
`designMode` can have `contenteditable` to make it editable. Then, the editable
elements should works as in the `contenteditable` mode rather than in the
`designMode`. Therefore, current `HTMLEditor::IsInDesignMode()` returns
wrong state when the finalization is called asynchronously or when an editing
host in a shadow DOM whose composed document is in the `designMode`.
This patch fixes known cases of these issues with improving the finalization
(and re-initialization with the new editing mode) and the caller side in
`Document`.
Differential Revision: https://phabricator.services.mozilla.com/D216022
MaybeEditorDeletedSourceNode was defined on nsIDragService but is more appropriately defined on nsIDragSession. This was not an issue previously since those were the same object.
Differential Revision: https://phabricator.services.mozilla.com/D211074
Updates each client of the nsContentUtils method to get the right drag session -- the one for the widget that is currently the source or target of the drag session.
The change to nsDOMWindowUtils::DispatchDOMEventViaPresShellForTesting() supports the change to WidgetDragEvent::InitDropEffectForTests() and enabled a
large number of test fixes in the next patch.
Differential Revision: https://phabricator.services.mozilla.com/D211067
As far as testing on Chrome, they don't dispatch any events during setting
text control value (including `compositionupdate` and `compositionend`).
However, we dispatch `compositionupdate`, `compositionend`, `beforeinput` and
`input` synchronously. Therefore, `input` event listener may run again with
the old value. This may make web apps confused because they may not expect
the nested `input` event listener call which is not caused by user intention
nor a `Document.execCommand` call. Therefore, we should stop dispatching
the nested `beforeinput` and `input` events which are caused by committing
composition for setting value since the value will be updated soon, so,
the input caused by committing composition does not occur actually. However,
`compositionend` event should be fired even in the nested event loop because
the web apps may manage whether they has a composition with a pair of
`compositionstart` and `compositionend` event listeners even though that won't
work on Chrome.
Additionally, the nested `compositionupdate` and `compositionend` event may
cause a `Document.execCommand` call. However, that must be unexpected behavior
for web apps and anyway the value will be overwritten to the new value.
Therefore, let's make `Document::ExecCommand` do nothing in the situation.
Differential Revision: https://phabricator.services.mozilla.com/D213756
Currently, the `<br>` element type -- whether normal `<br>` element or padding
`<br>` element for empty editor or last line -- is managed by the flags of
`nsINode`. Therefore, changing the flag does not cause mutation, so
`IMEContentObserver` cannot observe the type changes. However,
`ContentEventHandler` treats the padding `<br>` elements as invisible.
Therefore, when a `<br>` element becomes a padding one, `IMEContentObserver`
needs to notify IME of atext removed notification, and also when a `<br>`
element becomes a normal one (i.e., visible), `IMEContentObserver` needs to
notify IME of a text added notification.
Therefore, this patch makes `EditorBase` disconnect the `<br>` element
temporarily to make `IMEContentObserver` observable the type change.
Depends on D211698
Differential Revision: https://phabricator.services.mozilla.com/D211699
`nsDOMAttributeMap::GetAttribute` creates `dom::Attr` so that it's not cheap.
Instead it should access `Element::mAttrs` with the accessors or
`BorrowedAttrInfo`.
Differential Revision: https://phabricator.services.mozilla.com/D208087
`while (RefPtr<Attr> attr = attributes->Item(0))` causes a warning in
`nsDOMAttributeMap::IndexedGetter()` because of out of bounds. Additionally,
we should not make a loop with live DOM tree information if the loop updates
the DOM tree. Therefore, this patch makes it collect all attributes first
before touching the DOM tree.
Depends on D207240
Differential Revision: https://phabricator.services.mozilla.com/D207241
Although from the maintenance cost point of view, we should not duplicate
`EditorBase::DeleteRangesWithTransaction`, but let's add a wrapper for it
for making the callers simpler.
Differential Revision: https://phabricator.services.mozilla.com/D203854
The default value of `<textarea>` may be changed during reframes of the
corresponding `nsTextControlFrame`. Then, the `TextEditor` and the anonymous
subtree is recreated. In this moment, `IMEContentObserver` will restart to
observer the anonymous subtree after the editor is completely initialized,
but new default value which is caused by a mutation under `<textarea>` is
copied at recreating the anonymous subtree. Therefore, `IMEContentObserver`
fails to notify the text change before a further selection change.
For solving this issue, this patch makes `TextControlState` notifies
`IMEContentObserver` of default value change at recreating a new `TextEditor`.
Therefore, this patch may cause redundant text change notifications for IME.
Currently, I have a plan to fix bug 854272 to carry `TextEditor` instance and
the anonymous subtree over to new `nsTextControlFrame`. So, I believe that
this approach is reasonable for now (It'd be easier if we could add new
`nsString` to `TextControlState` without increasing the instance size, though).
Differential Revision: https://phabricator.services.mozilla.com/D197261
`beforeinput` event shouldn't be fired if it's caused by JS. However, we
dispatch it when the call is by chrome script or an addon because there is
no user input emulation API for WebExtension and builtin editors make the
change undoable only when JS changes the editor value with
`Document.execCommand`. Therefore, addons may want to use
`Document.execCommand` for making the change undoable.
On the other hand, nested calls of `Document.execCommand` makes the error
handlings in editor classes too complicated. Therefore, we don't allow that.
However, this causes that if web apps intercept `beforeinput` events and
prevents the default and calls `document.execCommand`, the first call of
web apps may be first nested call if the `beforeinput` event is caused by
a call of `Document.execCommand` in addon.
Therefore, this patch makes `Document` stores whether `ExecCommand` is called
by content or chrome/addon. And if the call is improperly nested, keep stopping
handling the command, but allows if and only if the first call is by
chrome/addon.
Differential Revision: https://phabricator.services.mozilla.com/D198357
It allows multiple edit action preserves `Selection` when updating the DOM tree.
However, most callers do not use `finally` to reset the state, and this makes
edit action handling complicated in some edge cases. Therefore, let's stop
supporting this feature. If Thunderbird requires the feature, the developers
should request additional param for preserving `Selection` like the preceding
patch.
Depends on D196004
Differential Revision: https://phabricator.services.mozilla.com/D196005
`nsIEditor.setShouldTxnSetSelection` can preserve selection across multiple
editing. Therefore, we cannot manage the state only in the stack.
It's used only in comm-central, and used only with `insertNode` and
`deleteNode`. Therefore, adding new param to them to preserve selection
must be enough.
While I'm writing this patch, I realized that `input` event is not fired
by these methods because nobody set a placeholder transaction. That may
lead Thunderbird only IME crash bugs due to `IMEContentObserver` is not
notified editor properly. Therefore, this may fix some Thunderbird only
crashes.
Note that `deleteNode` should not update selection. However, I'm not 100%
sure that. Therefore, I add new param to `deleteNode` too. However,
some reviewers think it's unnecessary, I'll remove it before landing.
Finally, `beforeinput` and `input` caused by the method calls start updating
selection. However, I think that it should be better behavior. If Thunderbird
needs to guarantee that selection is set to whether the user expected when
it calls these methods with preserving selection.
Differential Revision: https://phabricator.services.mozilla.com/D196004
Chrome handles text direction change as a block level format command. I.e.,
Chrome sets `dir` attributes of enclosing editable blocks of selected leaf
nodes. However, aligning to this may require a lot of change and Thunderbird
may require the traditional behavior.
On the other hand, it's obviously wrong thing that `Ctrl` + `Shift` + `X` in an
editable element changes the direction of entire the document since the `<body>`
may not be editable.
Therefore, this patch just changes the direction change target from `<body>`
to active editing host if it's an `HTMLEditor`.
Differential Revision: https://phabricator.services.mozilla.com/D195838
This is a simple mistake of the previous patch. The code path is originally for
a left click handling. Therefore, there is no check whether the click point is
in a selection range because in that case, left click should collapse selection.
However, the selection should not be collapse when it's a right click in a
selection range because the context menu target is the selection range.
The `ui.mouse.right_click.collapse_selection.stop_if_non_collapsed_selection`
pref is set to `true` by default. Therefore, the existence of a non-collapsed
selection has hidden this bug. However, if it's set to `false`, this always
happens. Additionally, editor does not set ancestor limiter of selection if the
root element is editable [1]. I think that we can now remove this special path,
but it's risky. Therefore, this patch just adds the new check into the method.
1. https://searchfox.org/mozilla-central/rev/ce4599d3d4e20e34cb6db68f255c3dff1aec246b/editor/libeditor/EditorBase.cpp#5448,5450-5451
Differential Revision: https://phabricator.services.mozilla.com/D193529
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
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
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
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
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