- From: Johannes Wilm <johannes@fiduswriter.org>
- Date: Sat, 11 Feb 2017 00:18:17 +0100
- To: Piotr Koszuliński <p.koszulinski@cksource.com>
- Cc: Alexandre Elias <aelias@google.com>, Dave Tapuska <dtapuska@chromium.org>, Chong Zhang <chongz@chromium.org>, "public-editing-tf@w3.org" <public-editing-tf@w3.org>
- Message-ID: <CABkgm-QL+D1ksfm7GgSxNZkxwf8zmmqPN+bw2eZ5=6B1B4WcJw@mail.gmail.com>
Hey, as this was getting quite complex, I have tried to list all the proposals I could find in one document and I have given editing access to those who came up with proposals so far. Let me know if you need write access. Otherwise, ehre is comment access for eveyrone else: https://docs.google.com/document/d/1uE3Whzp_zlGBh3giBtyJYcHm3hdTC-PVeyDMFsBerF8/edit?usp=sharing In terms of beforeinput events during IME, I am currently in favor of Alexandre's proposal A5 (next alternatives: A4 or no change) In terms of cancellable beforeinput event, I am in favor of no change. I don't think I have seen any reasonable argument for why we should make anything except IME non-cancelable. On Fri, Feb 10, 2017 at 11:56 PM, Johannes Wilm <johannes@fiduswriter.org> wrote: > > > On Wed, Feb 8, 2017 at 3:59 PM, Piotr Koszuliński < > p.koszulinski@cksource.com> wrote: > >> Hey, >> >> I won't try to go too deep into how IME related events should work >> because I don't know IME mechanisms and all its variations well enough, >> despite working with cE for more than 5 years. Perhaps, this answers some >> questions like how hard IME is actually and what's the average knowledge >> about it, even amongst quite experienced RTE developers ;). >> >> Anyway, I'd like to rather focus on how non-preventable the >> beforeinput event can be to make any value for CKEditor 5. I hope it will >> provide some context for the discussion. >> >> >> ### Text insertion ############ >> >> A couple of months ago I created a PoC of CKEditor 5's typing feature >> working based on the beforeinput event available at that time in Blink [1]. >> Unfortunately, I can't quickly check how the editor would behave if the >> event wasn't cancelled, but that would be very similar to how the editor >> needs to work without the beforeinput event. >> >> So how it works now? >> >> 1. We use a mutation observer to catch the input (typed characters). >> There's a special case when selection isn't empty when the user starts to >> type. We needed to hardcode the unsafe keys and delete the selected content >> on keydown. Otherwise, typing a single letter might cause hundreds of >> mutations if selection crossed some complicated content. We must avoid that. >> 2. We diff the DOM with our virtual DOM implementation to get a >> simplified form of the mutations. Browser may fire dozens of them, while >> for us it can be just a few changed text nodes or removed elements. >> 3. Then we analyse the mutations. We try to find a fragment of removed >> and inserted text, plus, the position of the selection after the change. >> 4. Then, if a feature (in this case, the typing feature) can handle >> certain mutations (i.e. they were not too complex) it applies the necessary >> changes to the model. >> 5. The changes in the model are converted to the virtual DOM. >> 6. If virtual DOM differs from the real DOM, minimal changes are applied. >> >> This architecture allows us to: >> >> * Apply understandable changes to the model, without re-rendering the >> DOM. This is crucial to support IME because some changes in the DOM break >> the composition (see the "IME" section in [1]). >> * Re-render the DOM before paint happens if changes were rejected by the >> editor. That, fortunately, needs to happen very rarely, but it's nice that >> there's no flickering anyway. >> >> How would beforeinput simplify our implementation? >> >> * We wouldn't need to listen to mutations and normalize them (1. & 2.). >> * We wouldn't need that ugly unsafe keys handler meant to empty the >> selection before a character is inserted (1.). >> * We would avoid the diffing mechanism, which is quite complex already >> despite missing few edge cases with spell checking or auto correction (3.). >> * We would have a perfect clarity whether the inserted space was meant to >> be a space or non-breaking space (it's problem to learn that when it's at >> the end of a block). >> * Etc, etc. >> > > > Shouldn't you have the same information iof you listened to all the > compositionupdate events (and these events actually delivered accurate > data)? > > >> >> So, that's the profit even if we can't cancel the event. It's still >> a pretty significant simplification, comparing to what we have to do now. >> >> However, there's one nasty case which may still require hacking if the >> event isn't cancelled. It's how the editor can delete the content itself >> when the user is typing over a non-empty selection. We can't let the >> browser do that because we wouldn't know how to convert those changes to >> the model (and sometimes it might simply be impossible). In general, there >> are a couple of options here. >> >> * If we'd be able to cancel all beforeinput events, that would be >> perfect, because we'd be able to handle the deletion of the content by >> ourselves first, and then we'd insert the typed characters. >> * If the beforeinput event is not cancellable, then: >> * it'd be nice if for the non-empty selection there would be >> a beforeinput with type=deleteContent fired before beforeinput with >> type=insert* (that would natively split the process into two steps – >> deletion and insertion), >> * alternatively, we should be able to change the DOM >> on beforeinput event without breaking the native insertion itself (then we >> can simply delete the selected content and set selection in a correct >> place, where the new character should be inserted). >> >> One of these options must be true because, otherwise, we won't be able to >> use the event. We'd still need to base on some ugly heuristic for >> discovering keys which are about to delete the content of the selection. >> >> What I don't know is how these options apply to IME. Let's assume that >> its events are non-cancellable, so we get some beforeinput event of delete* >> type followed by insertCompositionText. The deletion part is unclear for me >> because the insertion might've been in a middle of composition (so you get >> deleteCompositionText + insertCompositionText) or it might be the first >> composed character. What do we get in this case? >> >> I'm asking because I assume that when the user is composing already, the >> browser will never do some significant DOM changes. Composition would >> normally only touch the text nodes in a certain block, but not the block >> itself. Besides, while composition takes place, we're not able to re-render >> the DOM anyway, because that breaks the composition (see the "IME section >> in [1]). So, if something is wrong, we need to wait for the composition to >> finish anyway. But this is acceptable because I don't expect significant >> changes to be required. Maybe just some inline styling. >> >> However, if the insertion starts the composition, then the content which >> was previously selected might contain multiple blocks, tables, etc. and we >> must handle deletion of that piece ourselves. So, at least in this case, we >> must be able to either act upon inserComopositionText or there must be a >> separate deleteContent event. >> >> Uhh... that was about text insertion. >> >> >> ### Other beforeinput types ################## >> >> A non-cancellable beforeinput for the text insertion (and text deletion) >> is acceptable (with couple limitations, as I tried to explain above). >> However, other before input events must be cancellable. Otherwise, there >> will be quite pointless. >> >> For example, how do we handle the backspace and delete keys now? We >> listen to keydown, discover which key was pressed and with what modifiers >> and delete the content. We might not be able to implement "delete word" or >> "delete soft line" very precisely, but these are really minor issues. So, >> in this case the before input wouldn't give us anything. Actually, it'd be >> even worse than listening to the keydown event because we can cancel the >> keydown event. >> >> The same with text formatting – we can easily listen to CTRL+B to know >> whether someone wants to bold a text. We can cancel the keydown event. It'd >> be much worse if we had to listen to the beforeinput event and fix the DOM >> broken by the browser which incorrectly applied some <b> tag. The >> beforeinput event would only help with localizing the keystroke (in some >> languages it won't be CTRL+B). >> >> And so on, and so on. >> >> I can understand that IME makes some beforeinput events non-cancellable. >> But I totally don't understand why would deleteContentForward or >> insertUndeorderList be non-cancellable too (as was proposed in the document >> [2]). The set of non-cancellable events should be minimal. Otherwise, the >> situation is not going to improve. >> >> >> >> [1] https://github.com/w3c/editing/issues/149 >> [2] https://docs.google.com/document/d/1yPZEkHl_WOPjVeilZjE1 >> XmlyjLCe-uS7THI0SboyrMM/edit# >> >> -- >> Best Regards, >> Piotrek Koszuliński | CKEditor Lead Developer >> -- >> CKSource – http://cksource.com | Follow CKSource on: Twitter >> <http://twitter.com/cksource> | Facebook >> <http://www.facebook.com/cksource> | Google+ >> <https://plus.google.com/+CKSource> | LinkedIn >> <http://www.linkedin.com/company/cksource> >> >> On Wed, Feb 8, 2017 at 12:46 PM, Johannes Wilm <johannes@fiduswriter.org> >> wrote: >> >>> >>> >>> On Wed, Feb 8, 2017 at 3:56 AM, Alexandre Elias <aelias@google.com> >>> wrote: >>> >>>> OK, thanks for the clarifications. >>>> >>>> For me the bottom line I want to achieve is to have 1-to-1 mapping >>>> between IME commands intended to mutate text and beforeinput+input pairs. >>>> I don't like the idea of splitting any one of them into fragmentary pieces >>>> nor of generating phantom ones not corresponding to any text mutation. >>>> That generates unnecessary side effects and is difficult to reason about. >>>> >>>> Sometimes this would cause "natural" platform differences based on the >>>> different behavior of the actual IMEs, and that's fine because that likely >>>> means a different user-facing UX that JS would also need to conform to. On >>>> Android in the replacement scenario described, there is exactly one >>>> mutation where the nodes are both collapsed and replaced by the new word, >>>> so there should be exactly one input event. On Mac OS X there is first a >>>> visible collapse at the beginning of the composition, then (later on) a >>>> change to the new word, so there should be exactly two input events. I'm >>>> okay with such "natural" complexity but not with artificial >>>> spec-originating complexity. >>>> >>>> The idea of supporting a "preventDefault" on a fragmentary or phantom >>>> event is particularly alarming to me, because I think "preventDefault" >>>> should always be implemented by UAs as a simple early-return not performing >>>> some action. >>>> >>> But the implication of "preventDefault" on a phantom event is that the >>>> UA needs to proactively change the text when preventDefault is called but >>>> do nothing when it isn't, which is weird and bound to lead to a cascade of >>>> complexity. In my way of seeing things, "cancelability" is not a sane >>>> basis for fragmenting events, and the fragmenting is even counterproductive >>>> to permitting workable cancelability. (That's why I assumed the reason for >>>> the split might be a "cannot-replace" assumption.) >>>> >>> >>> That wasn't ever the intention. But course, having IME behave more >>> similarly across browsers would be an advantage. It used to be the case >>> that Chrome on desktop at the end of the composition would first remove the >>> entire compositionstring and would then readd it. This was very convenient >>> and it is why we made the last two events. From you description of it, you >>> either no longer have those two things happening or you just don't have it >>> on Android. That is less ideal. >>> >>> Ultimately I cannot see why IME input should not be standardized in some >>> way when everything else is standardized. >>> >>> >>> Imagine if instead of having keyboard, every country had inevented a >>> diferent inut device. Most developers would likely support the devices of >>> Germany, US, UK, France. But the input devices of Denmark and Nicaragua >>> would have more difficulty finding traction. Some Asian countries that >>> mainly use IME have a lot of population and Android is more popular than >>> many desktop operating systems, but a lot of richtext editing is mainly >>> confined to desktop (mobile clients often just have a function to write >>> two-three words without styling which is realistic for someone on a metro >>> to be doing) and a lot of things are mainly done in the European languages. >>> >>> >>> For example, we may think that everyone should be able to write a W3C >>> spec on their mobile phone in any possible langage, but in practice it will >>> almost always be on done on dekstop and it will almost always be with >>> keyboard input. In order to get support for the 1% of writers who will use >>> IME anyway, it would be of great help for the IME in those 1% to behave the >>> same way and not have 100 different IMEs with different behavor as that >>> will mean that the JS developer will have to spend much more time than what >>> is reasonable on something that is ultimately doesn't make any economic >>> sense. >>> >>> So instead of dealing with all this complexity and hundreds of different >>> ways of doing it, JS editors often decide that it's "good enough" to just >>> diff the DOM before and after and then have a rough idea of what the user >>> was trying to do. >>> >>> >>>> >>>> > I don't quite get what you mean by combining steps two and three. >>>> Step two was the reinsertion of the initial composition string into the >>>> DOM. Step three is the change during the composition. There will usually be >>>> many step threes, but only one step two. >>>> >>>> I simply meant combining step 2 into the first of the step 3s. >>>> >>>> > There is one problem in that compositionend with data="" could mean >>>> the composition has been cancelled or that the final compositionstring is >>>> empty. >>>> >>>> I propose to solve it always sending another step-3-style >>>> insertCompositionText("") before the compositionEnd in the case that the >>>> text is cleared, and no input event in the cancellation case. Then there >>>> would be no need to ever look at the data field of compositionEnd. >>>> >>> >>> If it doesn't read the data attribute of compositionEnd, then the JS >>> will have to follow all the compositionupdate events to figure out what the >>> final string will be, right? And as long as the beforeinput events related >>> to IME cannot be canceled and one has to wait for the entire IME string to >>> be done, the JS will have to calculate and combine what the total >>> targetrange of the composition is, right? If we don't really give the JS >>> developers anythign new with the beofreinput event, why would it be used? >>> Why wouldn't they just continue to diff the relevant part of the DOM? >>> >>> >>>> >>>> > Btw -- just to make it clear because this seems to have been a >>>> common misconception between JS developers and browser developers in the >>>> past: When we ask for these things to be cancelable, in 80% of cases this >>>> is not because we want to stop the user from doing things. It's more than >>>> we want to do the corresponding DOM changes in JS code, because they are >>>> specific to the JS editor the user is currently using and they may not >>>> necessarily make sense to the browser. >>>> >>>> That's useful context. But my take from this is that beforeinput >>>> preventDefaulting in *any* form cannot be used to meet this use case, at >>>> least on Android. Reason: on Android, we need to call the IME with >>>> "restartInput()" whenever the text changes unexpectedly, which fully >>>> reinitializes the IME and cancels ongoing compositions. This call is not >>>> at all desirable or needed if the JS editor is doing essentially the same >>>> thing as the default implementation would have. But unfortunately, there >>>> is no sane way for UAs to know whether the JS is "trying" to stop the >>>> action or if it's "trying" to recreate it. We'd have to bias towards >>>> oversending or undersending restartInput, likely via unreliable >>>> heuristics. The bugginess would be severe with either kind of bias. >>>> >>>> An alternate proposal: what if, when JS modifies the DOM within the >>>> scope of any "input" event, then the UA would run a before/after comparison >>>> to verify whether the summation of JS changes wound up changing the >>>> plain text distillation of the DOM (and therefore whether it's provable >>>> that the IME can sit blissfully unaware that anything strange happened). >>>> If the plain text representation changed, then the UA would always send >>>> restartInput and cancel composition, as UAs largely do in response to >>>> unexpected JS changes today. But if the only thing that changed was >>>> styling or other rich DOM substructure, the UA would *not* send >>>> restartInput and it would also reconstruct the composition range to keep it >>>> at the same plain-text-character offsets against the new DOM nodes. >>>> >>> >>> >>> Ok, this would kind of be to babysit the JavaScript, right? The problem >>> is that the plaintext distillation may eb slightly different, if for >>> example, the JavaScript uses animated gifs for some of the letters, or if >>> it needs to insert an empty space node. So I would prefer to say that all >>> preventdefualting of beforeinput will always jsut prevent the DOM update >>> from going through, but not for the action behdind it to be cancelled (we >>> did discuss at an earlier meeting if it was possible to make two types of >>> preventdefault to be able to distinguish between them). But yes, your >>> proposal does sound better than what we had until now and should work under >>> almost all cricumstances (editors that insert animated gifs just have to >>> add those when the composition is done). >>> >>> >>>> >>>> In this model, the JS editor would need to stash a copy of the previous >>>> DOM at time of "beforeinput", allow the "input" to happen, and then >>>> reconstruct the rich structure. Then we could avoid the entire can of >>>> worms of what particular IME events are "cancelable" or not and how to work >>>> around cases where they are not. >>>> >>> >>> I don't understand. Keeping the DOM at the start of the composition and >>> diffing when it's done, etc. is what is happening already. The beforeinput >>> event seems to not add much value for that. >>> >>> I thought you had just made a suggestion on how to make beforeinput >>> events during IME cancelable. >>> >>> To sum up, these two would give an advantage over todays situation: >>> >>> 1. Have all five beforeinput events, of which the middle three are not >>> cancelable and the first two only happen if one is recomposing. The 1st and >>> the last of these events can be used by JS to adjust the IME so that it >>> happens where it should and the final result is placed according to its own >>> logic. >>> >>> 2. Have one, two or three different input events that are cancelablein >>> so that the JS can manage the DOM updates itself. >>> >>> What gives hardly any advantage over today's situation: >>> >>> * Have one or two noncancelable beforeinput events that are not >>> surrounded by cancelable ones. >>> >>> What cripples the beforeinput event for most use cases even on desktop: >>> >>> * Make most beforeinput events non-cancelable. >>> >>> >>> >>> The only advantage left of having the beforeinput event that I can see >>> is: >>> >>> * handling UA button clicks and keyboard shortcuts >>> >>> * I understand that some editors don't monitor how the selection >>> changes, so they may not have known where the selection was before >>> something happened when it is done. >>> >>> >>> The handling of UA native buttons is further complicated by the fact >>> that browsers have a concept of a global undo stack, whereas all JS editors >>> we have been able to find use a undo stack that is specific to one >>> contenteditable host. As long as there is just one editing host on a page >>> or one encloses all editing hosts in iframes, this doesn't seem to be a >>> problem, but in all other cases it will mean that under some circumstances >>> the undo and redo buttons will not behave as expected. From Safri we even >>> heard they will not be able to turn these buttons on and off as needed. So >>> what we will be shipping will nor work correctly for history in Safari >>> right from the start. >>> >>> Which leaves us with buttons for richtext operations such as "make bold" >>> and "make italic". As far as I know, these are only shipped with Safari, so >>> really only Safari would need to add these. >>> >>> >>>> >>>> -- >>>> Alex >>>> >>>> On Mon, Feb 6, 2017 at 7:44 PM, Johannes Wilm <johannes@fiduswriter.org >>>> > wrote: >>>> >>>>> >>>>> >>>>> On Tue, Feb 7, 2017 at 4:00 AM, Alexandre Elias <aelias@google.com> >>>>> wrote: >>>>> >>>>>> On Mon, Feb 6, 2017 at 6:18 PM, Johannes Wilm < >>>>>> johannes@fiduswriter.org> wrote: >>>>>> >>>>>>> >>>>>>> >>>>>>> On Tue, Feb 7, 2017 at 12:23 AM, Alexandre Elias <aelias@google.com> >>>>>>> wrote: >>>>>>> >>>>>>>> Hi, I'm the maintainer of IME on Android. I'll be happy to attend >>>>>>>> the conference call next week. As you've surmised, Android does need to >>>>>>>> perform a DOM change to merge two nodes "later". However, I disagree that >>>>>>>> those 5 steps are somehow needed. Our plan is to send a single >>>>>>>> insertCompositionText beforeinput event instead of 5 events. >>>>>>>> >>>>>>> >>>>>>> Nice to meet you Alexandre! >>>>>>> >>>>>>> It's a bit unfrotunate that you haven't been able to participate in >>>>>>> the last 3 years of discussions about this subject (I think some people >>>>>>> have even been discussing this for more than 8 years), and it seems that >>>>>>> the mailing list isn't as alive any more as it once used to be, but I'll do >>>>>>> my best to give the reasoning why we came to the conclusion that these >>>>>>> events are needed. I would also recommend consulting the various open and >>>>>>> closed issues on github and to consult the archive of the mailing list. >>>>>>> Also, various Google people have been behind a lot if not most of the >>>>>>> various various concepts, so they can probably give you more background >>>>>>> about this as well. >>>>>>> >>>>>>> >>>>>>>> >>>>>>>> Arguments why each is not needed: >>>>>>>> >>>>>>>> > 1. deleteByComposition --This step is only needed when >>>>>>>> recomposing. A composed word can go across element boundaries, so this may >>>>>>>> delete more than just contents of a text node. (fx " He<b>ll</b><i>o >>>>>>>> fish</i>!"). This step needs to be executed at the moment your Android IME >>>>>>>> changes the DOM, whether this is at the moment the user taps the word and >>>>>>>> the underline appears or at a later stage. >>>>>>>> >>>>>>>> There's no need for a separate "delete" event, because >>>>>>>> insertion-to-replace-range is general enough to represent a deletion range >>>>>>>> as well. I prefer to reserve "delete" events exclusively for intended IME >>>>>>>> deletions (e.g. select word and press backspace). >>>>>>>> >>>>>>> >>>>>>> But I am a little confused: From the proposal Chong sent in, it >>>>>>> sounded like you just wouldn't have any beforeinput event for this initial >>>>>>> deletion. That would create a range of different problems, such as: >>>>>>> >>>>>> >>>>>> I agree we should not hide any editing information from JS. I am >>>>>> saying that event 2/3 can encompass the deletion. An implied, wrong >>>>>> assumption underlying your argument seems to be that an insertion operation >>>>>> can only ever add new text but not remove existing text. >>>>>> >>>>> >>>>> >>>>> No, that must be a misunderstanding. I don't know why you would think >>>>> that. As I said previsouly, if beforeinput events during IME are >>>>> cancelable, 1 (deletion) and 2 (addition cshould be combinable into one >>>>> single event, >>>>> >>>>> >>>>> I don't quite get what you mean by combining steps two and three. Step >>>>> two was the reinsertion of the initial composition string into the DOM. >>>>> Step three is the change during the composition. There will usually be many >>>>> step threes, but only one step two. >>>>> >>>>> The reason there is a step one and two at all is that the IME converts >>>>> the composition string from being something that can contain a complex >>>>> html-structure to just be a plaintext string (in most cases anyway). >>>>> >>>>> So step 1 will remove "He<b>l</b>p" and step 2 will re-add it as >>>>> "Help". Combining step 1 + 2 should work if step 2 is also cancelable. >>>>> Combining step 2 and 3, or maybe 1 and 2 and 3 (?) would mean that we go >>>>> straight from "He<b>l</b>p" to "Hel". and then the next two step 3 would >>>>> add "l" and "o". In many cases the JS will probably be able to guess what >>>>> the individual parts of this combination of 1/2/3 initially were (what part >>>>> was just about turning it into a plaintext and which part was then about >>>>> modifying the plaintext), but it would seem a bit meshed and I'm not sure >>>>> one always can determine it. Nevertheless, if iME input is cancelable, then >>>>> this does sound better than what was on the table previosuly. >>>>> >>>>> >>>>> >>>>> >>>>>> In reality, insertions are always *replacements* of the content of >>>>>> the caret/selection/composition with text (for example, if you select text >>>>>> with the mouse and then type "a" on a physical keyboard, no deletion event >>>>>> is sent). >>>>>> >>>>> >>>>> right. That'sw hy we have targetranges. But the difference for >>>>> keyboard inout is that it is cancelable and there is no automatic >>>>> normalization to plaintext. This is different than the situation with IME. >>>>> >>>>>> >>>>>> >>>>>>> * The more advanced editors today are moving toward a model where >>>>>>> they hold a json version of the document which is separate from the DOM. >>>>>>> They only make adjustments to the DOM when needed, and if the user changes >>>>>>> something about the DOM, they make adjustments to the json document. The >>>>>>> json version is the authoritative copy of the document. For this to work, >>>>>>> they need to know about any change to the DOM. If you make user-initiated >>>>>>> DOM changes that are not causing any beforeinput event at all, the >>>>>>> beforeinput event is somewhat useless, aand they will have to continue to >>>>>>> monitor user initiated DOM-changes in other ways. >>>>>>> >>>>>>> * In a collaborative editor, if you make a change to the DOM of one >>>>>>> user, and the JS is not being made aware of this change, then it won't >>>>>>> notify the collaborators of this change, and so the collaborator will ahve >>>>>>> different versions of the document. Again, the point of beforeinput events >>>>>>> will be gone. JS develoeprs will use mutation observers or some other >>>>>>> technology instead. >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> >>>>>>>> > 2. insertCompositionText -- Also this step only needs to happen >>>>>>>> at the moment only for recompositions. It reinserts the word from step one, >>>>>>>> but this time as plaintext in one element (fx "Hello" => "<i>Hello >>>>>>>> fish</i>") >>>>>>>> >>>>>>>> On Android because of the "late" timing, this merge operation would >>>>>>>> happen in the same message loop task as step 3, so there is no need for >>>>>>>> this event. We prefer to go directly from "He<b>ll</b><i>o fish</i>" -> >>>>>>>> "<i>Help<i>". >>>>>>>> >>>>>>> >>>>>>> >>>>>>> Yes, in a perfect world, where all IME-related events are >>>>>>> cancelable, this could be done and would be preferable, as for example >>>>>>> Yosin has pointed out ( https://github.com/w3c/input-e >>>>>>> vents/issues/45#issuecomment-261427648 ). We had a long discussion >>>>>>> during the fall of 2015 about this, and among other ones several developers >>>>>>> from Chromium eventually convinced us here that IME-events cannot be >>>>>>> guaranteed to be cancelable. Even moving the caret to somewhere else during >>>>>>> the composition may somehow crash the IME (hwo this is possible is a bit of >>>>>>> a mystery to me as a JS developer). >>>>>>> >>>>>>> One could then say ok, combine 1 and 2 and make them both >>>>>>> non-cancelable. The problem with that is that the browser doesn't always >>>>>>> know the seamntic meaning of the various DOM elements used within a >>>>>>> document and it may end up making decisions of what to delete that are >>>>>>> problematic. >>>>>>> >>>>>> >>>>>> I've been trying to figure out where these claims about IME from some >>>>>> Chromium team members came from exactly and haven't figured it out, nobody >>>>>> has a precise memory. They seem to be based on a vague fears rather than >>>>>> concrete knowledge of how IMEs behave. I agree with your instinct that the >>>>>> assumptions behind it don't make too much sense, that's why I think we >>>>>> should hold off before we commit to a complicated model based on those >>>>>> assumptions. >>>>>> >>>>> >>>>> Well, maybe you guys need to discuss that internally. Until now what >>>>> we said here is that we will assume the worst case scenario (that IMEs not >>>>> being allowed to directly modify the DOM will lead to them crashing) and >>>>> then in a future version to hopefully get one that doesn't crash. >>>>> >>>>> Btw -- just to make it clear because this seems to have been a common >>>>> misconception between JS developers and browser developers in the past: >>>>> When we ask for these things to be cancelable, in 80% of cases this is not >>>>> because we want to stop the user from doing things. It's more than we want >>>>> to do the corresponding DOM changes in JS code, because they are specific >>>>> to the JS editor the user is currently using and they may not necessarily >>>>> make sense to the browser. >>>>> >>>>> >>>>> >>>>>> >>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> However, rniwa@apple.com has told us that on OS X, the standard >>>>>>>> platform behavior is to merge the nodes at time of composition start. >>>>>>>> Therefore, on OS X step 2 is still needed and there would be 2 beforeinput >>>>>>>> events in total, but on Android there would be only 1. This represents a >>>>>>>> substantive platform difference that I think it makes sense to allow to >>>>>>>> differ in the spec. I don't think we should try to artificially >>>>>>>> synchronize the platforms by always sending 2 events -- on Android this >>>>>>>> would simply result in unnecessary work and side effects that would never >>>>>>>> be seen by the user. >>>>>>>> >>>>>>> >>>>>>> I think you should instead consider making this two events on >>>>>>> Android. Android is really great, but text editing in Chrome on Android is >>>>>>> really problematic especially when it comes to IME recomposition, as I am >>>>>>> sure you are aware. I have tried various keyboard, and but even on >>>>>>> mainstream sites such as Facebook, using a Google-provided keyboard, >>>>>>> recomposition tends to just mess up entire sentences, throw random words >>>>>>> around, deleting or merging words that are close to what one is trying to >>>>>>> recompose, etc. >>>>>>> >>>>>> >>>>>> Right, we are in process of fixing all of these bugs and expect to >>>>>> get the remaining ones fixed in M58/M59 timeframe. Anyway, this doesn't >>>>>> address my point. Personally, I believe that firing additional unnecessary >>>>>> events will prove harmful to both UAs and JS editors -- in reality an >>>>>> atomic IME change that just happened, but you are proposing to drip-feed it >>>>>> into many separate events. Your proposal doesn't provide JS any additional >>>>>> information (it just splits information into pieces), so therefore I don't >>>>>> think it can possibly be needed for any use case either. >>>>>> >>>>>> >>>>>> >>>>>>> Speed is not as much a concern anyway because it all depends on the >>>>>>> human who is interacting with it, but in addition these really major issues >>>>>>> mean that recomposition as it exists on Android as of today is not very >>>>>>> useful. In addition there are the various issues that JS developers have >>>>>>> complained about for a while: no compositionstart event, etc. . I am sure >>>>>>> you know the list of grievances with it all too well. >>>>>>> >>>>>> >>>>>> We should always be firing compositionStart today. Feel free to file >>>>>> a bug against me if you know of a case where we don't. >>>>>> >>>>> >>>>> I recently sent a list of prioritized bugs from several JS editor >>>>> projects to the Chromium team that they had requested from em. I assume >>>>> they forwarded those issues relevant to Android to you. >>>>> >>>>>> >>>>>> >>>>>>> >>>>>>> Not knowing the details, but I could imagine you can check for event >>>>>>> listeners, and only if those are present you make it two events. >>>>>>> >>>>>>> But as an alternative, and to try to get a bit closer to both your >>>>>>> and Yosin's position, how about this: We make two IME models, one for IMEs >>>>>>> where the beforeinput events can be cancelled in which step 1 and 2 are >>>>>>> merged and one where they cannot be cancelled where they are separate. >>>>>>> >>>>>> >>>>>> Disagree, we should keep things as simple as possible. I want us to >>>>>> fire a minimum of events and avoid complicated logic forking. I don't want >>>>>> us to introduce permanent complexity into the platform for the sake of a >>>>>> short-term compromise. >>>>>> >>>>> >>>>> Well, you said that Apple does one thing and you do another. So either >>>>> the two of you can agree or you don't. If you cannot agree, we'll have to >>>>> have two different models. >>>>> >>>>> In theis scenario, if the Chrome model consists of just cutting out 4 >>>>> of 5 events on Android, then as I tried to explain in the last few emails >>>>> and the comments on the proposal doc, the event will no longer function to >>>>> build an editor on top of. At least not without combining it with mutation >>>>> observers and other technologies. >>>>> >>>>> Having a model where IME events are cancelable is really something we >>>>> all hoped to do in a future version of the spec. If the situation is such >>>>> that Chromium/Android would prefer to do this right now, whereas Apple >>>>> prefers to stay with the non-cancelable IME-model then that would not seem >>>>> like terribly different models. >>>>> >>>>> >>>>>> >>>>>> >>>>>>> >>>>>>>> >>>>>>> > 4. deleteCompositionText -- removed (fx "help"): It removed the >>>>>>>> text from the underline and it may not be the entire composition. >>>>>>>> >>>>>>>> > 5. insertFromComposition -- adds "help" permanently, and gives >>>>>>>> the JS the opposrtunity to rebuild the complex HTML structure lost in step >>>>>>>> 1. >>>>>>>> >>>>>>>> Step 3 is already permanent. The fact that there is still an >>>>>>>> active composition underline at the time of step 3 does not make it somehow >>>>>>>> temporary. It has already been injected into the DOM and caused all side >>>>>>>> effects. So the JS should rebuild its complex structure at time of event >>>>>>>> 3, and events 4/5 are redundant. >>>>>>>> >>>>>>> >>>>>>> When a composition starts, they temporarily pause most activities >>>>>>> because they are not really allowed to intervene. Then, once the >>>>>>> composition is finished, they deal with the finished text. input. For >>>>>>> example, in step 5 they may reapply some partial styling that was lost in >>>>>>> step 1. >>>>>>> >>>>>> >>>>>> "compositionend" event is fired at the same timing that steps 4/5 >>>>>> would be, isn't it sufficient for this use case? >>>>>> >>>>> >>>>> There is one problem in that compositionend with data="" could mean >>>>> the composition has been cancelled or that the final compositionstring is >>>>> empty. The distinction between 4 and 5 is needed if 2, 3 & 4 are >>>>> non-cancelable. If they are cancelable, then one should be able to combine >>>>> 1 and 2, and skip 4 and 5 and the JS would continously make any adjustments >>>>> it needs to the DOM (while taking into consideration what the >>>>> compositionstring is at any moment). >>>>> >>>>> >>>>>> >>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> The reason you state for the proposed change is that "On Android >>>>>>>>> it’s very common for IME to start composition whenever a cursor is moved >>>>>>>>> onto a word. This is primarily intended to passively show an underline to >>>>>>>>> the user (to indicate what would be replaced *if* user selects an alternate >>>>>>>>> spelling)." >>>>>>>>> >>>>>>>>> If such tapping leads to actual DOM changes, then the JS needs to >>>>>>>>> know about those(step 1/2). But if you don't change the DOM immediately and >>>>>>>>> only do so at a later stage when you "really" start the composition, then >>>>>>>>> you can also wait until that stage. >>>>>>>>> >>>>>>>>> >>>>>>>>> So these steps are needed on allplattforms, no matter whether or >>>>>>>>> not you change how IMEs work on Android. >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> Adding aelias@ to make sure he is able to make the call on the >>>>>>>>>> 14th. >>>>>>>>>> >>>>>>>>>> dave. >>>>>>>>>> >>>>>>>>>> On Fri, Feb 3, 2017 at 1:33 AM, Johannes Wilm < >>>>>>>>>> johannes@fiduswriter.org> wrote: >>>>>>>>>> >>>>>>>>>>> Could we get the person or people who came up with these changes >>>>>>>>>>> due to Android to participate in the call on the 14th? I think it's very >>>>>>>>>>> important to have them invovled in this discussion. >>>>>>>>>>> >>>>>>>>>>> On Fri, Feb 3, 2017 at 10:21 AM, Johannes Wilm < >>>>>>>>>>> johannes@fiduswriter.org> wrote: >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Fri, Feb 3, 2017 at 10:18 AM, Johannes Wilm < >>>>>>>>>>>> johannes@fiduswriter.org> wrote: >>>>>>>>>>>> ... >>>>>>>>>>>> >>>>>>>>>>>>> Right now I cannot see any purpose of the beforeinput event >>>>>>>>>>>>> with these changes applied, but maybe I am missing something? >>>>>>>>>>>>> >>>>>>>>>>>>> >>>>>>>>>>>> I need to restarct that. I guess it could still be useful to >>>>>>>>>>>> stop native bold/italic buttons from making their own, non-controlled DOM >>>>>>>>>>>> changes. It's just for text input that it is irrelevant. And IME will >>>>>>>>>>>> continue to be a mess. >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>>> Johannes Wilm >>>>>>>>>>>> Fidus Writer >>>>>>>>>>>> http://www.fiduswriter.org >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> Johannes Wilm >>>>>>>>>>> Fidus Writer >>>>>>>>>>> http://www.fiduswriter.org >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Johannes Wilm >>>>>>>>> Fidus Writer >>>>>>>>> http://www.fiduswriter.org >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Johannes Wilm >>>>>>> Fidus Writer >>>>>>> http://www.fiduswriter.org >>>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> -- >>>>> Johannes Wilm >>>>> Fidus Writer >>>>> http://www.fiduswriter.org >>>>> >>>> >>>> >>> >>> >>> -- >>> Johannes Wilm >>> Fidus Writer >>> http://www.fiduswriter.org >>> >> >> > > > -- > Johannes Wilm > Fidus Writer > http://www.fiduswriter.org > -- Johannes Wilm Fidus Writer http://www.fiduswriter.org
Received on Friday, 10 February 2017 23:18:55 UTC