Skip to content

Commit 9ad612a

Browse files
committed
Ignore Chrome's caretPositionFromPoint results when the move to the end of the line
FIX: Fix vertical cursor motion in Chrome around decorations with bottom borders or margins. Closes codemirror/dev#1612
1 parent 8f1a6d7 commit 9ad612a

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

src/cursor.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,12 @@ export function posAtCoords(view: EditorView, coords: {x: number, y: number}, pr
175175
if (pos) ({offsetNode: node, offset} = pos)
176176
} else if (doc.caretRangeFromPoint) {
177177
let range = doc.caretRangeFromPoint(x, y)
178-
if (range) {
179-
;({startContainer: node, startOffset: offset} = range)
180-
if (!view.contentDOM.contains(node) ||
181-
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
182-
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
183-
node = undefined
184-
}
178+
if (range) ({startContainer: node, startOffset: offset} = range)
185179
}
180+
if (node && (!view.contentDOM.contains(node) ||
181+
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
182+
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x)))
183+
node = undefined
186184
// Chrome will return offsets into <input> elements without child
187185
// nodes, which will lead to a null deref below, so clip the
188186
// offset to the node size.
@@ -217,11 +215,7 @@ function posAtCoordsImprecise(view: EditorView, contentRect: Rect, block: BlockI
217215
return block.from + findColumn(content, into, view.state.tabSize)
218216
}
219217

220-
// In case of a high line height, Safari's caretRangeFromPoint treats
221-
// the space between lines as belonging to the last character of the
222-
// line before. This is used to detect such a result so that it can be
223-
// ignored (issue #401).
224-
function isSuspiciousSafariCaretResult(node: Node, offset: number, x: number) {
218+
function isEndOfLineBefore(node: Node, offset: number, x: number) {
225219
let len, scan = node
226220
if (node.nodeType != 3 || offset != (len = node.nodeValue!.length)) return false
227221
for (;;) { // Check that there is no content after this node
@@ -238,9 +232,17 @@ function isSuspiciousSafariCaretResult(node: Node, offset: number, x: number) {
238232
return textRange(node as Text, len - 1, len).getBoundingClientRect().right > x
239233
}
240234

235+
// In case of a high line height, Safari's caretRangeFromPoint treats
236+
// the space between lines as belonging to the last character of the
237+
// line before. This is used to detect such a result so that it can be
238+
// ignored (issue #401).
239+
function isSuspiciousSafariCaretResult(node: Node, offset: number, x: number) {
240+
return isEndOfLineBefore(node, offset, x)
241+
}
242+
241243
// Chrome will move positions between lines to the start of the next line
242244
function isSuspiciousChromeCaretResult(node: Node, offset: number, x: number) {
243-
if (offset != 0) return false
245+
if (offset != 0) return isEndOfLineBefore(node, offset, x)
244246
for (let cur = node;;) {
245247
let parent = cur.parentNode
246248
if (!parent || parent.nodeType != 1 || parent.firstChild != cur) return false

0 commit comments

Comments
 (0)