- From: Johannes Wilm <johannes@fiduswriter.org>
- Date: Fri, 10 Feb 2017 23:56:40 +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-SXWBTUauq6ZDy+EpRYGDbuqGHmR0=hYWM=5jwaQTKMmw@mail.gmail.com>
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_WOPjVeilZjE1XmlyjLCe- > 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
Received on Friday, 10 February 2017 22:57:20 UTC