Skip to content
Snippets Groups Projects
Commit 1d00df9e authored by Marijn Haverbeke's avatar Marijn Haverbeke
Browse files

Make backspace across lines work in Chrome Android

(when there is a gutter)

Issue #4637
parent cfcad600
No related branches found
No related tags found
No related merge requests found
......@@ -223,11 +223,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
......
......@@ -13,6 +13,7 @@ import { gecko, ie_version } from "../util/browser"
import { contains, range, removeChildrenAndAdd, selectInput } from "../util/dom"
import { on, signalDOMEvent } from "../util/event"
import { Delayed, lst, sel_dontScroll } from "../util/misc"
import { chrome, android } from "../util/browser"
// CONTENTEDITABLE INPUT STYLE
......@@ -219,16 +220,28 @@ export default class ContentEditableInput {
}
pollSelection() {
if (!this.composing && this.readDOMTimeout == null && !this.gracePeriod && this.selectionChanged()) {
let sel = window.getSelection(), cm = this.cm
this.rememberSelection()
let anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset)
let head = domToPos(cm, sel.focusNode, sel.focusOffset)
if (anchor && head) runInOp(cm, () => {
setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll)
if (anchor.bad || head.bad) cm.curOp.selectionChanged = true
})
if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) return
let sel = window.getSelection(), cm = this.cm
// On Android Chrome (version 56, at least), backspacing into an
// uneditable block element will put the cursor in that element,
// and then, because it's not editable, hide the virtual keyboard.
// Because Android doesn't allow us to actually detect backspace
// presses in a sane way, this code checks for when that happens
// and simulates a backspace press in this case.
if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) {
this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs})
this.blur()
this.focus()
return
}
if (this.composing) return
this.rememberSelection()
let anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset)
let head = domToPos(cm, sel.focusNode, sel.focusOffset)
if (anchor && head) runInOp(cm, () => {
setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll)
if (anchor.bad || head.bad) cm.curOp.selectionChanged = true
})
}
pollContent() {
......@@ -370,6 +383,12 @@ function posToDOM(cm, pos) {
return result
}
function isInGutter(node) {
for (let scan = node; scan; scan = scan.parentNode)
if (/CodeMirror-gutter-wrapper/.test(scan.className)) return true
return false
}
function badPos(pos, bad) { if (bad) pos.bad = true; return pos }
function domTextBetween(cm, from, to, fromLine, toLine) {
......
......@@ -18,8 +18,9 @@ export let mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent)
export let phantom = /PhantomJS/.test(userAgent)
export let ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent)
export let android = /Android/.test(userAgent)
// This is woefully incomplete. Suggestions for alternative methods welcome.
export let mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent)
export let mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent)
export let mac = ios || /Mac/.test(platform)
export let chromeOS = /\bCrOS\b/.test(userAgent)
export let windows = /win/i.test(platform)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment