Re: Proposal to ammend the composition event spec.

So, after a bunch more discussion, I'd like to propose the following,
the second point of which involves changing the spec.

1. All dom mutations resulting from composition must be strictly bound
between compositionstart and compositionend
2. textInput should be fired before compositionend

E.g.

to type "wo" -> 我

user "w"
event compositionstart
("w")

user "o"
("wo")

user <space>
("我")

user <space> (to commit the composition)
("")
event textInput (cancelable)
("我")
event compositionend

Notes: I have omitted compositionupdate events for simplicity. The
fact that the user hits space twice is just how the IME example I am
using works (many pinyin IMEs do this).

If the user hit <ESC> instead of the final <space>, the composition
would be cancelled - in this case, textInput would simply not fire,
and compositionend would be fired with no composition text in the
composition state.

If the event handler prevents default for textInput, compositionend
would again still fire. Canceling the compositionend is meaningless.

To summarize again, compositionend must always fire for every
compositionstart, and changes related to the composition must always
be bound between the two events no matter what. We feel the above is
the best option because:
a) Satisfies the use case of having mutations being bound by
composition events. This is extremely important from our work with
using these events to date.
b) Preserves textInput's existing semantics of firing before the final
composition is committed. This satisfies James Su's concerns stated
earlier.
c) Is consistent with existing Firefox behavior (to the extent that's
possible, given that FF doesn't yet support textInput)

Please let me know if I need to clarify anything.
Thanks

Dan

On Sat, May 29, 2010 at 10:39 AM, James Su <suzhe@chromium.org> wrote:
>
>
> 在 2010年5月28日 上午7:30,Ojan Vafai <ojan@chromium.org>写道:
>>
>> On Fri, May 21, 2010 at 4:17 PM, James Su <suzhe@chromium.org> wrote:
>>>
>>> More points about the second proposal:
>>> For the second proposal, we do:
>>> 1. fire compositionupdate event after mutating the dom
>>> 2. delete composition string before firing compositionend event
>>> 3. fire textInput after compositionend but before inserting the text
>>> So that:
>>> 1. We can know when composition mode starts by hooking compositionstart
>>> event
>>> 2. We can get updated composition string in compositionupdate handler
>>> synchronously
>>> 3. We can know when composition mode finishes by hooking compositionend
>>> event
>>> 4. textInput event can be cancelled in order to revert the DOM tree
>>> completely.
>>
>> What's the use-case for canceling the confirmed composition? I can
>> see canceling individual keypresses, but I don't see why someone would want
>> to cancel the composition when the user just confirmed it.
>
> textInput event is defined as cancellable. Not sure if there is any real
> world use-case.
>
>>
>> Firing textInput before each time the DOM is modified does make
>> compositionUpdate a bit redundant, but it makes textInput more useful by
>> making it consistently happen before the DOM is ever modified from a
>> user-initiated text input.
>
> The text being composed and the confirmed text are different. I don't think
> we should mix them. The effect of textInput event for a node is to append a
> piece of text to existing content, while compositionUpdate is not. And
> textInput is already in specification for quite a long time, it's not good
> to change its behavior which may break backward compatibility.
>
>>>
>>> About the deleting and inserting again issue: because compositionend and
>>> textInsert events are fired in the same event loop iteration, it should not
>>> cause additional rendering. So the visual and performance impact would
>>> be negligible.
>>> The only issue of this proposal is: we need to change composition* events
>>> to non-cancellable. But anyway, cancelling these events make completely no
>>> sense. If somebody really wants to cancel the composition process, he/she
>>> can just cancel the keydown event.
>>> Regards
>>> James Su
>>> 在 2010年5月18日 上午7:49,Daniel Danilatos <daniel@danilatos.com>写道:
>>>>
>>>> The spec should make it clear that mutations must be bounded between
>>>> compositionstart and compositionend events.
>>>>
>>>> Background:
>>>>
>>>> https://bugs.webkit.org/show_bug.cgi?id=31902
>>>> Hironori has asked me to write up this email arguing for adjusting the
>>>> spec..
>>>>
>>>> Summary:
>>>>
>>>> >From our implementation experience, it is broken not to bound
>>>> mutations with compositionstart and compositionend events. not having
>>>> this severely limits their utility - and requires large amounts of
>>>> hacky workaround code, even involving asynchronous logic.
>>>> Firefox already has the correct behaviour, and it is off firefox that
>>>> we largely based the spec (so the spec should be adjusted)
>>>> The fix for webkit is already implemented - it was just rejected
>>>> because it supposedly doesn't match the spec; once the spec is
>>>> adjusted, both Webkit and FF will be in line with eachother with
>>>> respect to the composition events.
>>>> The tricky thing to consider is, when should a textinput event be
>>>> fired. This is a secondary issue to the strong requirement, that
>>>> mutations must be bounded by composition events. The options then seem
>>>> to be:
>>>>
>>>> (Compatible with existing spec) Fire textInput after the composition
>>>> has ended - thus textInput would no longer be a pre-input-event, but
>>>> really, it never was, as the dom is mutating before the event anyway.
>>>> Currently, webkit creates the composition text, then removes it again,
>>>> just so it can then fire the textInput event, and if not cancelled,
>>>> will then insert the content.
>>>> (Compatible with existing spec) If textInput really, really must fire
>>>> before input, even though the dom has already been mutating from the
>>>> composition, then delete the composition, but do that BEFORE the
>>>> compositionend event. then fire a regular cancellable textInput. In my
>>>> opinion this seems wasteful, though.
>>>> (Incompatible with existing spec) Fire textInput before every change.
>>>> This is more generally consistent, especially with other proposals to
>>>> extend textInput (or introduce a similar event) that fires before
>>>> every change to the DOM at all, including for things like paste, undo,
>>>> and deletion. For the use case where the application wants to know
>>>> when some content is ready and in a consistent state (i.e. not during
>>>> composition), a post-change event is more applicable. Such an event
>>>> does not have to fire after every single change.
>>>> We shouldn't fear the final option above - the composition events spec
>>>> is still in its infancy. Now is the time to make meaningful changes.
>>>>
>>>> Best,
>>>> Dan
>>>>
>>>
>>
>
>

Received on Tuesday, 15 June 2010 06:09:08 UTC