@@ -20,7 +20,9 @@ export default function ContentEditableInput(cm) {
2020 this . cm = cm
2121 this . lastAnchorNode = this . lastAnchorOffset = this . lastFocusNode = this . lastFocusOffset = null
2222 this . polling = new Delayed ( )
23+ this . composing = null
2324 this . gracePeriod = false
25+ this . readDOMTimeout = null
2426}
2527
2628ContentEditableInput . prototype = copyObj ( {
@@ -37,44 +39,23 @@ ContentEditableInput.prototype = copyObj({
3739 } ) , 20 )
3840 } )
3941
40- function startComposing ( data ) {
41- input . composing = { sel : cm . doc . sel , data : data , startData : data }
42- if ( ! data ) return
43- let prim = cm . doc . sel . primary ( )
44- let line = cm . getLine ( prim . head . line )
45- let found = line . indexOf ( data , Math . max ( 0 , prim . head . ch - data . length ) )
46- if ( found > - 1 && found <= prim . head . ch )
47- input . composing . sel = simpleSelection ( Pos ( prim . head . line , found ) ,
48- Pos ( prim . head . line , found + data . length ) )
49- }
50-
51- on ( div , "compositionstart" , e => startComposing ( e . data ) )
42+ on ( div , "compositionstart" , e => {
43+ this . composing = { data : e . data }
44+ } )
5245 on ( div , "compositionupdate" , e => {
53- if ( input . composing ) input . composing . data = e . data
54- else startComposing ( e . data )
46+ if ( ! this . composing ) this . composing = { data : e . data }
5547 } )
5648 on ( div , "compositionend" , e => {
57- let ours = input . composing
58- if ( ! ours ) return
59- if ( e . data != ours . startData && ! / \u200b / . test ( e . data ) )
60- ours . data = e . data
61- // Need a small delay to prevent other code (input event,
62- // selection polling) from doing damage when fired right after
63- // compositionend.
64- setTimeout ( ( ) => {
65- if ( ! ours . handled )
66- input . applyComposition ( ours )
67- if ( input . composing == ours )
68- input . composing = null
69- } , 50 )
49+ if ( this . composing ) {
50+ if ( e . data != this . composing . data ) this . readFromDOMSoon ( )
51+ this . composing = null
52+ }
7053 } )
7154
7255 on ( div , "touchstart" , ( ) => input . forceCompositionEnd ( ) )
7356
7457 on ( div , "input" , ( ) => {
75- if ( input . composing ) return
76- if ( cm . isReadOnly ( ) || ! input . pollContent ( ) )
77- runInOp ( input . cm , ( ) => regChange ( cm ) )
58+ if ( ! this . composing ) this . readFromDOMSoon ( )
7859 } )
7960
8061 function onCopyCut ( e ) {
@@ -237,7 +218,7 @@ ContentEditableInput.prototype = copyObj({
237218 } ,
238219
239220 pollSelection : function ( ) {
240- if ( ! this . composing && ! this . gracePeriod && this . selectionChanged ( ) ) {
221+ if ( ! this . composing && this . readDOMTimeout == null && ! this . gracePeriod && this . selectionChanged ( ) ) {
241222 let sel = window . getSelection ( ) , cm = this . cm
242223 this . rememberSelection ( )
243224 let anchor = domToPos ( cm , sel . anchorNode , sel . anchorOffset )
@@ -250,6 +231,11 @@ ContentEditableInput.prototype = copyObj({
250231 } ,
251232
252233 pollContent : function ( ) {
234+ if ( this . readDOMTimeout != null ) {
235+ clearTimeout ( this . readDOMTimeout )
236+ this . readDOMTimeout = null
237+ }
238+
253239 let cm = this . cm , display = cm . display , sel = cm . doc . sel . primary ( )
254240 let from = sel . from ( ) , to = sel . to ( )
255241 if ( from . line < display . viewFrom || to . line > display . viewTo - 1 ) return false
@@ -309,17 +295,20 @@ ContentEditableInput.prototype = copyObj({
309295 this . forceCompositionEnd ( )
310296 } ,
311297 forceCompositionEnd : function ( ) {
312- if ( ! this . composing || this . composing . handled ) return
313- this . applyComposition ( this . composing )
314- this . composing . handled = true
298+ if ( ! this . composing ) return
299+ this . composing = null
300+ if ( ! this . pollContent ( ) ) regChange ( this . cm )
315301 this . div . blur ( )
316302 this . div . focus ( )
317303 } ,
318- applyComposition : function ( composing ) {
319- if ( this . cm . isReadOnly ( ) )
320- operation ( this . cm , regChange ) ( this . cm )
321- else if ( composing . data && composing . data != composing . startData )
322- operation ( this . cm , applyTextInput ) ( this . cm , composing . data , 0 , composing . sel )
304+ readFromDOMSoon : function ( ) {
305+ if ( this . readDOMTimeout != null ) return
306+ this . readDOMTimeout = setTimeout ( ( ) => {
307+ this . readDOMTimeout = null
308+ if ( this . composing ) return
309+ if ( this . cm . isReadOnly ( ) || ! this . pollContent ( ) )
310+ runInOp ( this . cm , ( ) => regChange ( this . cm ) )
311+ } , 80 )
323312 } ,
324313
325314 setUneditable : function ( node ) {
0 commit comments