Proper ordering of input and selectionchange event handlers for Android IME

I'm currently working on improving the behavior of JavaScript event
handlers while entering text on Chrome for Android (see
http://crbug.com/737395 for context).

The Android InputConnection API (
https://developer.android.com/reference/android/view/inputmethod/InputConnection.html)
that input methods (e.g. on-screen keyboards) use to send text to an
application contains two methods (commitText() and setComposingText() that
perform both a text replacement and a selection move.

Currently, we implement these in Chrome by performing the following steps:

1. Compute the offsets where selection should be moved to after the
insertion (assuming JavaScript doesn't change the text).
2. Perform the insertion.
3. Run the JavaScript input event handler.
4. Move the selection to the offsets computed in step 1.
5. Run the JavaScript selectionchange event handler.

The obvious problem here (and the one I'm trying to solve) is that the
selection offsets computed in step 1 and applied in step 4 end up being
garbage if JavaScript changes the text in step 3.

We're evaluating several different approaches we can take to improve the
behavior here. One of them is to re-order the steps so we actually move the
selection to the offsets specified by the IME _before_ running the input
event handler. The new list of steps would be as follows:

1. Compute the offsets where selection should be moved to after the
insertion.
2. Perform the insertion.
3. Move the selection to the offsets computed in step 1.
4. Run the JavaScript input event handler.
5. Run the JavaScript selectionchange event handler.

The question we're not sure of is "is it ok to change the selection after
performing the insertion but before running the input event handler, taking
into account that from the IME's perspective, it's in some sense a single
operation"?

>From a spec point of view, the UI Events Working Draft says, about the
input event:
https://w3c.github.io/uievents/#event-type-input

"A user agent MUST dispatch this event immediately after the DOM has been
updated."

So this seems to preclude the change we're thinking about making, unless we
can consider the selection change to be part of the DOM mutation. If I type
on a keyboard into an editable region, the selection is moved before the
input event is fired, which is basically the same as the behavior we're
thinking about implementing. One important difference between a physical
keyboard and the IME API though is that the IME can say "insert this text,
and then move the selection all the way back to the start of the editable
region" as a single operation. So I'm a little worried that there might be
web apps out there that assume that when an input event is fired, the
selection is still at the location of the newly-inserted text; we might
break those apps in the rare case when an Android IME doesn't just want to
leave the selection at the end of the newly-inserted text.

Does this change seem safe, and is it allowed by the spec draft as
currently written?

Received on Thursday, 14 December 2017 01:34:28 UTC