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
HTMLSelectEventListener changes are needed, since currently that code works somewhat by accident given that
mTime often contains totally bogus values, like PR_IntervalNow(). Those changes then reveal issues also in
browser_editAddressDialog.js.
Differential Revision: https://phabricator.services.mozilla.com/D165618
We resolve editing commands on Linux and macOS to respect the system settings
of every key press when an `eKeyPress` event is sent to a remote process, and
it requires `WritingMode` at selection for arrow key handling for example.
Therefore, the parent process try to get the information.
However, in the case, the query succeeds only when IME has focus since
`ContentCacheInParent` does not have any data when IME does not have focus.
Therefore, `TextEventDispatcher::MaybeQueryWritingModeAtSelection` should
check the IME state before dispatching `eQuerySelectedText` event to avoid
the warnings and unnecessary runtime cost.
Differential Revision: https://phabricator.services.mozilla.com/D143901
Users may map reserved shortcut keys of Firefox/Thunderbird as an editing
command or a navigation command. Therefore if and only if an editable element
has focus and a reserved key combination is mapped to an editing command or
a navigation command by the system settings, we should allow to dispatch it
into the content and work it as what user expects.
With this change, keyboard only users may loose some shortcut keys to leave
from a web content which blocks keyboard focus in it. However, there may
be another reserved shortcut keys to escape from such web apps only with
keyboard because it's hard to think that all reserved shortcut keys conflict
with users' settings.
Differential Revision: https://phabricator.services.mozilla.com/D138009
Querying selection for getting writing mode may run script in the main process
if focus is in it. For avoiding new users of writing mode at selection **only**
when the value is required during an editable content has focus,
`TextEventDispatcher` should always store writing mode at receiving focus
notification.
Differential Revision: https://phabricator.services.mozilla.com/D138008
Currently, this feature is implemented only on Linux and macOS (see also
bug 1077515 and bug 1301497), and the code is really similar each other.
Additionally, it always tries to query selection to check whether the caret is
in vertical content or not if arrow keys are pressed. For avoiding a lot of
query, this patch makes `TextEventDispatcher` cache writing mode at every
selection change notification. However, unfortunately, it's not available when
non-editable content has focus, but it should be out of scope of this bug since
it requires a lot of changes.
Anyway, with this patch, we can write a mochitest only on Linux and macOS.
The following patch adds a test for this as a fix of bug 1103374.
Differential Revision: https://phabricator.services.mozilla.com/D102881
Currently, we don't allow keyboard events synthesized for tests retrieve native
key bindings in content process. However, due to this, we cannot test keyboard
navigation, deleting per word, etc on Linux and macOS either with mochitest
or WPT. For making better compatibility with the other browsers, we should
write WPT more with the test driver. Therefore, we should allow keyboard
events synthesized for tests retrieve native key bindings.
On the other hand, if we make them retrieve customized keyboard shortcuts
in the environment, some developers may not be able to run tests locally without
resetting their customization. Therefore, this patch makes `NativeKeyBindings`
set "standard" shortcut keys on the platform instead of retrieving actual
shortcut key results.
If referring the default shortcut key bindings is not good thing for
WebDriver/CDP, perhaps, `TextInputProcessor` should have a new flag which can
refer customized shortcut keys even in content process. But I think that it
should be done in another bug because some edit commands are mapped forcibly
like this patch.
https://searchfox.org/mozilla-central/rev/c03e8de87cdb0ce0378c0886d3c0ce8bbf9dc44e/remote/domains/parent/Input.jsm#82-102
Differential Revision: https://phabricator.services.mozilla.com/D102877
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.
find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
if [ -n "$interfaces" ]; then
if [[ "$interfaces" == *$'\n'* ]]; then
regexp="\("
for i in $interfaces; do regexp="$regexp$i\|"; done
regexp="${regexp%%\\\|}\)"
else
regexp="$interfaces"
fi
interface=$(basename "$path")
rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
if [ $hits -eq 0 ]; then
echo "Removing ${interface} from ${path2}"
grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
mv -f "$path2".tmp "$path2"
fi
done
fi
done
Differential Revision: https://phabricator.services.mozilla.com/D55444
Converts dom.keyboardevent.dispatch_during_composition and dom.keyboardevent.keypress.dispatch_non_printable_keys_only_system_group_in_content to static prefs. Removes the dispatch_during_composition entry from mobile.js, since it just redefines the same pref value.
Differential Revision: https://phabricator.services.mozilla.com/D42391
A lot of files include `nsIPresShell.h` even though currently they don't
need it. This patch removes the unnecessary inclusions.
Differential Revision: https://phabricator.services.mozilla.com/D25744
A lot of files include `nsIPresShell.h` even though currently they don't
need it. This patch removes the unnecessary inclusions.
Differential Revision: https://phabricator.services.mozilla.com/D25744
Synthesizing keyboard events is dangerous and such API is requested only by
fuzzing test. So, we should add it into FuzzingFunctions which is built
only when |ac_add_options --enable-fuzzing| is specified and enabled by
the pref.
This patch implements the API as synthesizing keyboard events in the focused
widget and the synthesized events are propagated as native key events except
APZ (because keyboard events are synthesized only in the process). This
behavior allows to test including any default action handlers such as
EventStateManager and setting WidgetGUIEvent::mWidget since some C++ handler
checks if it's nullptr.
Differential Revision: https://phabricator.services.mozilla.com/D5516
Currently, if an event is consumed in the main process, EventStateManager
does not send it to remote process. However, this is unexpected behavior
for some WidgetKeyboardEvent dispatchers. OS sometimes has consumed native
key events before sending applications. For example, Alt key on Windows
should activate menu bar of focused window but Alt key may be consumed before
focused window receives the event. In such case, we mark Alt keyboard event
as "consumed before dispatch", and chrome treat it like as its preventDefault()
is called in web content. (Note that for compatibility with other browsers,
the consumed state is not exposed to web content. So, Event.defaultPrevented
returns false in web content.)
Therefore, we need to treat "consumed" state and "cross process forwarding"
state separately. This patch makes calling WidgetEvent::PreventDefault()
always stops cross process forwarding for backward compatibility. Additionally,
for the special case mentioned above, this patch makes
WidgetEvent::PreventDefaultBeforeDispatch() take additional argument,
|aIfStopCrossProcessForwarding|. If this is CrossProcessForwarding::eStop,
the event won't be sent to remote process as same as calling PreventDefault().
Otherwise, CrossProcessForwarding::eHold, PreventDefaultBeforeDispatch() call
does not change "cross process forwarding" state. I.e., if the event's
StopCrossProcessForwarding() and PreventDefault() are not called until
EventStateManager::PostHandleEvent(), the event will be sent to remote process
as usual.
MozReview-Commit-ID: IQGWJvXetxV
UI Events declares that keypress event should be fired only when the keydown
sequence produces some characters. For conforming to UI Events and
compatibility with the other browsers, we should stop dispatching keypress
events for non-printable keys.
For getting regression reports, we should enable this new behavior only
on Nightly.
However, some web apps actually broken with the standardized behavior. For
protecting testers from known broken web apps, this patch introduces a
blacklist to take the traditional behavior under specific domain (and path in
it, optionally). Currently, docs.google.com and mail.google.com are set by
default.
MozReview-Commit-ID: HSrYX8LUB0p
For confirming to UI Events spec, we should dispatch "keydown" event and
"keyup" event even during in composition.
This patch makes only Nightly and early Beta start to dispatch those events
during a composition.
MozReview-Commit-ID: 8md7NtSdurJ
We have stopped dispatching "keypress" events for non-printable keys
and key combinations for conforming to UI Events and following the
other browsers.
However, this change hits a serious bugs of Google Docs, Google
Spreadsheets and Gmail. Until they will fix their bugs, we should
take back the traditional behavior for keeping Nightly usable for
any Nightly testers.
MozReview-Commit-ID: 9CyEbsFit1S
UI Events declares that keypress event should be fired only when the keydown
sequence produces some characters. For conforming to UI Events and
compatibility with the other browsers, we should stop dispatching keypress
events for non-printable keys.
For getting regression reports, we should enable this new behavior only
on Nightly and early Beta.
MozReview-Commit-ID: 5IIL9huejXH
Currently, we dispatch keypress event when Enter is pressed without modifiers
or only with Shift key. However, the other browsers dispatch keypress event
for Ctrl + Enter in any platforms even if it doesn't cause any text input.
So, we should fire keypress event for Ctrl + Enter even in strict keypress
dispatching mode.
Note that with other modifiers, it depends on browser and/or platform.
So, anyway, web developers shouldn't use keypress event to catch
Alt + Enter, Meta + Enter and two or more modifiers + Enter.
MozReview-Commit-ID: 3uUMkhL5VfJ
Chromium dispatches a keypress event when pressing Enter or Shift+Enter.
Actually, when user press them in <pre> element of HTML editor, ツ・n is inserted.
It makes sense to treat the key combinations as inputting text.
MozReview-Commit-ID: Hvx87MZtZkn
UI Events declares that keypress event should be fired when the keypress event
causes some text input. However, we're keeping our traditional behavior for
historical reasons because our internal event handlers (including event
handlers of Thunderbird) handles keypress events for any keys. Therefore,
for minimizing the side effect, we should stop kicking keypress event handlers
in the default event group in web content.
This patch adds new pref for enabling the standard behavior in web content.
Additionally, creates WidgetKeyboardEvent::IsInputtingText() for sharing the
check logic between TextEventDispatcher and TextEditor/HTMLEditor.
MozReview-Commit-ID: 3rtXdLBPeVC
When composition events are handled by content actually, widget receives
NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED notification. If focused content
is in a remote process, this is notified only when all sending composition
events are handled in the remote process. So, when widget receives the
notification can there is no composition in IME, that means that nobody is
composing composition at that time.
This patch adds TextEventDispatcher::IsHandlingComposition() which returns
false only when nobody has composition and makes TSFTextStore refer this
method because TSFTextStore needs to know if focused content has composition
in any cases.
MozReview-Commit-ID: F1ZZgFJAArD
In the parent process, every nsIWidget instance like nsWindow has TextEventDispatcher instance after dispatching a keyboard event or a composition event. Then, TextEventDispatcher manages whether there is composition and handles NotifyIME. However, PuppetWidget doesn't have it unless it synthesizes keyboard events or composition events for tests.
This causes PuppetWidget implementing nsIWidget::NotifyIME() with nsBaseWidget::NotifyIMEInternal() which is a virtual method only implemented by PuppetWidget. For consistent implementation around here, we should move NotifyIMEInternal() implementation to TextEventDispatcherListener::NotifyIME() which is called by TextEventDispatcher::NotifyIME(). Then, PuppetWidget can handle NotifyIME() easier.
This patch creates TextEventDispatcher::BeginInputTransactionFor() which takes pointer to a dispatching event and pointer to PuppetWidget. It emulates each corresponding event dispatcher method for managing composing state and begins input transaction for the dispatching event.
Unfortunately, this implementation is ugly due to duplicated code. However, this is enough for now. When we need to make TextEventDispatcher manage more states, we should add methods which are shared by both BeginInputTransactionFor() and event dispatcher method.
MozReview-Commit-ID: GeP028luZjR
IMEContentObserver may need to change notifications to send when TextInputProcessor begins input transaction. In current design, IMEContentObserver needs to retrieve IMENotificationRequests at every change. However, if nsIWidget returns a reference to its IMENotificationRequests, IMEContentObserver can call it only once.
For that purpose, this patch changes nsIWidget::GetIMENotificationRequests() to nsIWidget::IMENotificationRequestsRef() and make it return |const IMENotificationRequests&|. However, if the lifetime of the instance of IMENotificationRequest is shorter than the widget instance's, it's dangerous. Therefore, it always returns TextEventDispatcher::mIMENotificationRequests. TextEventDispatcher's lifetime is longer than the widget. Therefore, this guarantees the lifetime.
On the other hand, widget needs to update TextEventDispatcher::mIMENotificationRequests before calls of nsIWidget::IMENotificationRequestsRef(). Therefore, this patch makes TextEventDispatcher update proper IMENotificationRequests when it gets focus or starts new input transaction and clear mIMENotificationRequests when it loses focus.
Note that TextEventDispatcher gets proper requests both from native text event dispatcher listener (typically, implemented by native IME handler class) and TextInputProcessor when TextInputProcessor has input transaction because even if TextInputProcessor overrides native IME, native IME still needs to know the content changes since they may get new input transaction after that.
However, there may not be native IME handler in content process. If it runs in Android, PuppetWidget may have native IME handler because widget directly handles IME in e10s mode for Android. Otherwise, native IME handler is in its parent process. So, if TextInputHandler has input transaction in content process, PuppetWidget needs to behave as native event handler. Therefore, this patch makes PuppetWidget inherit TextEventDispatcherListener and implements PuppetWidget::IMENotificationRequestsRef().
MozReview-Commit-ID: 2SW3moONTOX
According to ATOK's behavior, IME may send different line breaker from its platform's standard. Therefore, we should treat \r as \n too.
Additionally, currently, TextComposition doesn't allow to input \n with composition. However, this was added for preventing to see odd control characters as boxes with code point. Therefore, we should allow \n for IMEs. (It was allowed, this limitation is unexpected when I reviewed the patch to reject control characters in TextComposition.)
MozReview-Commit-ID: DzGSMgp89Av
So, finally, Flush() should replace native line breakers in the composition string before dispatching composition events. However, if the composition string was set by Set(), i.e., it's already been replaced with native line breakers, we shouldn't try to do it again due to performance reason. Therefore, this patch adds |mReplacedNativeLineBreakers| to manage if it's already been called.
MozReview-Commit-ID: 5Y7ULWeP153
First of all, replacing native line breakers with XP line breakers needs to adjust offset and length of each TextRange. Therefore, we cannot just duplicate the code into TextEventDispatcher::PendingComposition::Flush().
For creating a new method to replace the native line breakers in PendingComposition::mString, we should separate range adjustment code to a static method, AdjustRange(), because we cannot use for loop simply because we need to adjust both mClauses and mCaret.
MozReview-Commit-ID: 5ycsN8EAs45
This patch creates NativeKey::DispatchKeyPressEventsWithRetrievedCharMessages() for dispatching eKeyPress event with mCommittedCharsAndModifiers when it stores following printable WM_(SYS)CHAR messages.
Using loop for dispatching eKeyPress event for every WM_(SYS)CHAR message is wrong because WidgetKeyboardEvent::mKeyValue is initialized with mCommittedCharsAndModifiers and it causes TextEventDispatcher dispatching multiple eKeyPress events at every call of MaybeDispatchKeypressEvents(). Therefore, if mKeyValue is "^^", eKeyPress event is dispatched 4 times --for the first message, eKeyPress events are fired for each "^" and for the second message, eKeyPress events are fired again for each "^"--. Therefore, when it handles WM_(SYS)KEYDOWN and it causes inputting one or more printable characters, it's the easiest way not to use HandleCharMessage().
The new method calls TextEventDispatcher::MaybeDispatchKeypressEvents() only once and it requests to call the callback method with new argument of MaybeDispatchKeypressEvents() when it needs to dispatch 2 or more eKeyPress events. Then, NativeKey::WillDispatchKeyboardEvent() can set each eKeyPress event to raw information of the message and proper modifier state.
With this change, we can dispatch multiple eKeyPress events with retrieved WM_(SYS)CHAR message information rather than retrieved information from active keyboard layout. Therefore, NeedsToHandleWithoutFollowingCharMessages() doesn't return true even when mCommittedCharsAndModifiers stores two or more characters.
FYI: there is a bug in test_keycodes.xul. That is, Alt+'A' of Greek keyboard layout should cause WM_SYSCHAR with a corresponding Greek character but ASCII characters are specified. Therefore, this patch includes the fix of these bugs
MozReview-Commit-ID: JVm7ZJVug0O
For making our code clearer by the stronger type check, we should change the anonymous enum for NS_TEXTRANGE_* to enum class whose name is "TextRangeType" and whose type is "RawTextRangeType" which is an alias of uint8_t.
Additionally, this also adds some utility methods for them.
Note that some lines which are changed by this patch become over 80 characters but it will be fixed by the following patches.
MozReview-Commit-ID: 76izA1WqTkp