w3c / input-events

Input Events
https://w3c.github.io/input-events/
Other
24 stars 16 forks source link

What is the intended/recommended approach to hijack composition events? #137

Open Azmisov opened 1 year ago

Azmisov commented 1 year ago

Neither specifications nor various online documentation are especially clear on how the events are intended to be used to take over composition editing control from the browser. Additionally, digging through the issues on github and testing various browsers, it is clear that the interpretation of the events has been in flux, especially considering the division into Level 1 and Level 2 specs. Here is what I have gathered so far:

Per my interpretation of the specs, originally the level 2 beforeinput composition events were, in order:

There is no way to completely hijack the composition events, mainly because it will ruin compatibility with existing IME's. As a compromise, while you won't have control of the actual composition events, the spec lets you track what parts of the DOM were removed (deleteByComposition) and what would be added (insertFromComposition) so you can undo the initial deletion if desired, and add the final composition text yourself in some way. It has been suggested by some (#122) that these events could be used to redirect the composition to occur in a separate, possibly hidden element, and port over the changes on the fly to the original element. However, it was observed that the IME's (or maybe it is the browsers) do not like getting redirected and will cancel the composition or otherwise exhibit quirky behavior. So it seems the only viable method for dealing with composition events presently is to wait for the composition to end and then cleanup/incorporate any changes. From what I gather, more deeply interfacing with IME's and composition is not possible with current API's, and would require something new such as the proposed EditContext (which also covers other deep editing integration cases, like controlling cursor/selection).

Observed behavior for various browsers, from my tests:

So for composition events, it seems the only guarantee you have is that insertCompositionText will fire, even with the supposed Level 2 spec'ed implementation of Safari/Webkit. Further, it seems from the discussion in #122, that at least the Chromium team has abandoned the other three composition events, so there are no plans for their implementation in the future.

It seems the current recommended approach to emulate the missing events is to use the composition[start,update,end] events. (As a side note, the order of composition events can be different, e.g. compositionupdate occurs before beforeinput for Firefox, but after for Chromium/Safari). Here's my take on emulating the events:

A bit more work, but seems like it is possible to do without the events after all. As it does require a fair bit of boilerplate just to replicate the Level 2 spec, it was proposed that insertCompositionText event be modified to allow some cancelation (see #134), letting the browser handle the deletion of inserted_range. However, as I commented there, it seems like a hacky solution when one could just implement the missing Level 2 events instead. Additionally, it wouldn't handle deleted_dom or affected_range.

Is this a fair assessment of the state of the Input Events spec currently? I surmise composition events are the only real stumbling block that has been run into for implementing the spec. Is the method I outlined for emulating the events what was intended/recommended by the spec writers, or is there a better way to go about this?

johanneswilm commented 1 year ago

@Azmisov AFAIK it's not possible to emulate the missing events as the composition buffer may be filled at which time part of the composition string will be committed to the DOM permanently and trying to remove it at that stage will cancel the entire composition. I have not tested it in practice though.

Azmisov commented 1 year ago

Okay, interesting. The idea was to only repair the DOM on compositionend, but you're saying even that would not be possible? I was also going to post an update, since I did some testing as well and the results were not great:

Also related, I have made a site to test composition events: https://azmisov.github.io/Input-Events-Tester/