- From: Ryan Landay <rlanday@chromium.org>
- Date: Tue, 20 Feb 2018 13:58:06 -0800
- To: public-editing-tf@w3.org
- Message-ID: <CACTDmNEKULX8W+Zfy5P22nOkQpG1bEYUACvpHQ0ZQu3f9YaFzA@mail.gmail.com>
Nearly all Android on-screen keyboards use the Android IME APIs for entering text: https://developer.android.com/reference/android/view/ inputmethod/InputConnection.html For example, with Gboard, when you start typing a word, it will open a composition, update the composition for each letter typed, and then end the composition when you hit the space bar to end the word. If you tap on another word, Gboard will set that word as the active composition, even before you start actually typing. This uses the InputConnection#setComposingRegion() method to move the composition range to an existing piece of text: *https://developer.android.com/reference/android/view/inputmethod/InputConnection.html#setComposingRegion(int,%20int) <https://developer.android.com/reference/android/view/inputmethod/InputConnection.html#setComposingRegion(int,%20int)>* In Chrome 64 and earlier, we never fired compositionstart or compositionupdate events in response to setComposingRegion(). However, we _would_ actually move or create the composition region, and fire compositionend when that region was closed out. I landed a change for Chrome 65 that will fix this, so setComposingRegion() now fires compositionstart if no composition range is open, and compositionupdate regardless of whether or not one is already open. The UI Events spec says that for compositionstart: https://www.w3.org/TR/uievents/#event-type-compositionstart > Some implementations MAY populate the data attribute of the compositionstart event with the text currently selected in the document (for editing and replacement). Otherwise, the value of the data attribute MUST be the empty string. On Android, selection and composition are usually two different ranges. Tapping on a new word will cause Gboard to change the composition range to contain that word, but the selection will just be a caret selection wherever you tapped. So my Chrome change always sends the empty string for this event. However, I wanted web developers to actually know what text is in the composition at this point, so I'm also firing a compositionupdate immediately afterward. Some developers from Basecamp (which develops at least two rich text editor web apps: Trix and Draft.js) were testing a beta of Chrome 65 and discovered that this change breaks their apps: https://bugs.chromium.org/p/chromium/issues/detail?id=812674 They feel that it's now difficult to tell when a composition is actually inserting or replacing text versus when a keyboard is just moving the composition. It seems that they were previously making use of the fact that Chrome was not sending the compositionstart event for the latter case. I think there's some operation they want to do with the new text after a composition is closed. I feel like there should be a better way to do this (e.g. using the beforeinput or input events in conjunction with compositionend?). So I think the change we're making brings Chrome into better alignment with the spec, but I'm interested in getting feedback, especially from developers of rich text editing applications, as to whether the spec could be changed somehow to make it more useful. E.g., should we be able to send the initial composition text in the data field of the compositionstart event, even if it's not selected? I also have a question about when fake key events with the 229 key code should be sent for composition updates. The spec says: https://www.w3.org/TR/uievents/#events-composition-key-events > During the composition session, keydown and keyup events MUST still be sent, and these events MUST have the isComposing attribute set to true. The language here is unclear to me and other Chrome developers about what should be done if the composition was changed in response to something other than a virtual or physical key press event. An example in a prior section shows a handwriting recognition IME apparently not sending keydown/keyup events (or are they just omitted from the example?): https://www.w3.org/TR/uievents/#events-composition-handwriting Right now, my code isn't sending key press events when a user taps on a word and Gboard moves the composition to a new word. This seems like the correct behavior (since there's no actual key being pressed and no text is actually being changed). However, I think the spec is generally unclear as to handle this case. Another issue in my opinion is that the spec for compositionupdate says: https://www.w3.org/TR/uievents/#event-type-compositionupdate > A user agent SHOULD dispatch this event during a composition session when a text composition system updates its active text passage with a new character, which is reflected in the string in data. However, it doesn't really say what to do if an IME is moving the composition to a new piece of text, or updating the composition by more than one character (both of these cases are extremely common). In summary: - Are the existing APIs sufficient for web developers to interpret when Gboard is editing text vs. just moving the composition range? - Does the behavior required by the spec as the Chrome editing engineers make sense for this case? - Whatever we decide, I think the spec should be made more clear about what should happen in these cases. Thanks, Ryan Landay
Received on Tuesday, 20 February 2018 21:58:36 UTC