Ver código fonte

Fix: IME composistion broken in empty paragraph in Safari.

farthinker 6 anos atrás
pai
commit
12b3f4bde0

+ 12 - 0
packages/ckeditor5-engine/src/view/renderer.js

@@ -102,6 +102,13 @@ export default class Renderer {
 		this.isFocused = false;
 
 		/**
+		 * Indicates if the view document is composing.
+		 *
+		 * @member {Boolean}
+		 */
+		this.isComposing = false;
+
+		/**
 		 * The text node in which the inline filler was rendered.
 		 *
 		 * @private
@@ -771,6 +778,11 @@ export default class Renderer {
 	 * @returns {Boolean}
 	 */
 	_domSelectionNeedsUpdate( domSelection ) {
+		// Remain DOM selection untouched while composing (#1782)
+		if ( this.isComposing ) {
+			return false;
+		}
+
 		if ( !this.domConverter.isDomSelectionCorrect( domSelection ) ) {
 			// Current DOM selection is in incorrect position. We need to update it.
 			return true;

+ 1 - 0
packages/ckeditor5-engine/src/view/view.js

@@ -105,6 +105,7 @@ export default class View {
 		 */
 		this._renderer = new Renderer( this.domConverter, this.document.selection );
 		this._renderer.bind( 'isFocused' ).to( this.document );
+		this._renderer.bind( 'isComposing' ).to( this.document );
 
 		/**
 		 * A DOM root attributes cache. It saves the initial values of DOM root attributes before the DOM element

+ 42 - 0
packages/ckeditor5-engine/tests/view/renderer.js

@@ -3641,6 +3641,48 @@ describe( 'Renderer', () => {
 				return viewData.repeat( repeat );
 			}
 		} );
+
+		// #1782
+		it( 'should leave dom selection untouched while composing', () => {
+			const { view: viewP, selection: newSelection } = parse( '<container:p>[]</container:p>' );
+
+			viewRoot._appendChild( viewP );
+			selection._setTo( newSelection );
+
+			renderer.markToSync( 'children', viewRoot );
+			renderer.render();
+
+			// mock IME typing in Safari: <p>[c]</p>
+			renderer.isComposing = true;
+			const domText = document.createTextNode( 'c' );
+			domRoot.firstChild.appendChild( domText );
+			const range = document.createRange();
+			range.setStart( domText, 0 );
+			range.setEnd( domText, 1 );
+			const domSelection = document.getSelection();
+			domSelection.removeAllRanges();
+			domSelection.addRange( range );
+
+			// <container:p>c[]</container:p>
+			viewP._appendChild( new ViewText( 'c' ) );
+			selection._setTo( [
+				new ViewRange( new ViewPosition( viewP.getChild( 0 ), 1 ), new ViewPosition( viewP.getChild( 0 ), 1 ) )
+			] );
+
+			renderer.markToSync( 'children', viewP );
+			renderer.render();
+
+			expect( domRoot.childNodes.length ).to.equal( 1 );
+			expect( domRoot.firstChild.childNodes.length ).to.equal( 1 );
+			expect( domRoot.firstChild.firstChild.data ).to.equal( 'c' );
+
+			const currentRange = domSelection.getRangeAt( 0 );
+			expect( currentRange.collapsed ).to.equal( false );
+			expect( currentRange.startContainer ).to.equal( domRoot.firstChild.firstChild );
+			expect( currentRange.startOffset ).to.equal( 0 );
+			expect( currentRange.endContainer ).to.equal( domRoot.firstChild.firstChild );
+			expect( currentRange.endOffset ).to.equal( 1 );
+		} );
 	} );
 
 	describe( '#922', () => {