@@ -13,6 +13,7 @@ import { gecko, ie_version } from "../util/browser"
1313import { contains , range , removeChildrenAndAdd , selectInput } from "../util/dom"
1414import { on , signalDOMEvent } from "../util/event"
1515import { Delayed , lst , sel_dontScroll } from "../util/misc"
16+ import { chrome , android } from "../util/browser"
1617
1718// CONTENTEDITABLE INPUT STYLE
1819
@@ -219,16 +220,28 @@ export default class ContentEditableInput {
219220 }
220221
221222 pollSelection ( ) {
222- if ( ! this . composing && this . readDOMTimeout == null && ! this . gracePeriod && this . selectionChanged ( ) ) {
223- let sel = window . getSelection ( ) , cm = this . cm
224- this . rememberSelection ( )
225- let anchor = domToPos ( cm , sel . anchorNode , sel . anchorOffset )
226- let head = domToPos ( cm , sel . focusNode , sel . focusOffset )
227- if ( anchor && head ) runInOp ( cm , ( ) => {
228- setSelection ( cm . doc , simpleSelection ( anchor , head ) , sel_dontScroll )
229- if ( anchor . bad || head . bad ) cm . curOp . selectionChanged = true
230- } )
223+ if ( this . readDOMTimeout != null || this . gracePeriod || ! this . selectionChanged ( ) ) return
224+ let sel = window . getSelection ( ) , cm = this . cm
225+ // On Android Chrome (version 56, at least), backspacing into an
226+ // uneditable block element will put the cursor in that element,
227+ // and then, because it's not editable, hide the virtual keyboard.
228+ // Because Android doesn't allow us to actually detect backspace
229+ // presses in a sane way, this code checks for when that happens
230+ // and simulates a backspace press in this case.
231+ if ( android && chrome && this . cm . options . gutters . length && isInGutter ( sel . anchorNode ) ) {
232+ this . cm . triggerOnKeyDown ( { type : "keydown" , keyCode : 8 , preventDefault : Math . abs } )
233+ this . blur ( )
234+ this . focus ( )
235+ return
231236 }
237+ if ( this . composing ) return
238+ this . rememberSelection ( )
239+ let anchor = domToPos ( cm , sel . anchorNode , sel . anchorOffset )
240+ let head = domToPos ( cm , sel . focusNode , sel . focusOffset )
241+ if ( anchor && head ) runInOp ( cm , ( ) => {
242+ setSelection ( cm . doc , simpleSelection ( anchor , head ) , sel_dontScroll )
243+ if ( anchor . bad || head . bad ) cm . curOp . selectionChanged = true
244+ } )
232245 }
233246
234247 pollContent ( ) {
@@ -370,6 +383,12 @@ function posToDOM(cm, pos) {
370383 return result
371384}
372385
386+ function isInGutter ( node ) {
387+ for ( let scan = node ; scan ; scan = scan . parentNode )
388+ if ( / C o d e M i r r o r - g u t t e r - w r a p p e r / . test ( scan . className ) ) return true
389+ return false
390+ }
391+
373392function badPos ( pos , bad ) { if ( bad ) pos . bad = true ; return pos }
374393
375394function domTextBetween ( cm , from , to , fromLine , toLine ) {
0 commit comments