Skip to content

Commit d9dbde7

Browse files
committed
Skip atomic ranges for pointer selections that aren't handled by a selection style
FIX: Make sure all pointer selections skip atomic ranges. Closes codemirror/dev#1606
1 parent 748bfe7 commit d9dbde7

File tree

3 files changed

+29
-24
lines changed

3 files changed

+29
-24
lines changed

src/cursor.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,27 @@ export function skipAtomicRanges(atoms: readonly RangeSet<any>[], pos: number, b
358358
}
359359
}
360360

361+
export function skipAtomsForSelection(atoms: readonly RangeSet<any>[], sel: EditorSelection) {
362+
let ranges = null
363+
for (let i = 0; i < sel.ranges.length; i++) {
364+
let range = sel.ranges[i], updated = null
365+
if (range.empty) {
366+
let pos = skipAtomicRanges(atoms, range.from, 0)
367+
if (pos != range.from) updated = EditorSelection.cursor(pos, -1)
368+
} else {
369+
let from = skipAtomicRanges(atoms, range.from, -1)
370+
let to = skipAtomicRanges(atoms, range.to, 1)
371+
if (from != range.from || to != range.to)
372+
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to)
373+
}
374+
if (updated) {
375+
if (!ranges) ranges = sel.ranges.slice()
376+
ranges[i] = updated
377+
}
378+
}
379+
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel
380+
}
381+
361382
export function skipAtoms(view: EditorView, oldPos: SelectionRange, pos: SelectionRange) {
362383
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1)
363384
return newPos == pos.from ? pos : EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1)

src/domchange.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import {EditorView} from "./editorview"
2-
import {inputHandler, editable} from "./extension"
2+
import {inputHandler, editable, atomicRanges} from "./extension"
33
import {contains, dispatchKey} from "./dom"
44
import browser from "./browser"
55
import {DOMReader, DOMPoint, LineBreakPlaceholder} from "./domreader"
66
import {findCompositionNode} from "./docview"
77
import {EditorSelection, Text, Transaction, TransactionSpec} from "@codemirror/state"
8+
import {skipAtomsForSelection} from "./cursor"
89

910
export class DOMChange {
1011
bounds: {
@@ -124,6 +125,8 @@ export function applyDOMChange(view: EditorView, domChange: DOMChange): boolean
124125
if (view.inputState.lastSelectionTime > Date.now() - 50) {
125126
if (view.inputState.lastSelectionOrigin == "select") scrollIntoView = true
126127
userEvent = view.inputState.lastSelectionOrigin!
128+
if (userEvent == "select.pointer")
129+
newSel = skipAtomsForSelection(view.state.facet(atomicRanges).map(f => f(view)), newSel)
127130
}
128131
view.dispatch({selection: newSel, scrollIntoView, userEvent})
129132
return true

src/input.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {ViewUpdate, PluginValue, clickAddsSelectionRange, dragMovesSelection as
66
logException, mouseSelectionStyle, PluginInstance, focusChangeEffect, getScrollMargins,
77
clipboardInputFilter, clipboardOutputFilter} from "./extension"
88
import browser from "./browser"
9-
import {groupAt, skipAtomicRanges} from "./cursor"
9+
import {groupAt, skipAtomsForSelection} from "./cursor"
1010
import {getSelection, focusPreventScroll, Rect, dispatchKey, scrollableParents} from "./dom"
1111
import {applyDOMChangeInner} from "./domchange"
1212

@@ -376,29 +376,8 @@ class MouseSelection {
376376
if (this.dragging === false) this.select(this.lastEvent)
377377
}
378378

379-
skipAtoms(sel: EditorSelection) {
380-
let ranges = null
381-
for (let i = 0; i < sel.ranges.length; i++) {
382-
let range = sel.ranges[i], updated = null
383-
if (range.empty) {
384-
let pos = skipAtomicRanges(this.atoms, range.from, 0)
385-
if (pos != range.from) updated = EditorSelection.cursor(pos, -1)
386-
} else {
387-
let from = skipAtomicRanges(this.atoms, range.from, -1)
388-
let to = skipAtomicRanges(this.atoms, range.to, 1)
389-
if (from != range.from || to != range.to)
390-
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to)
391-
}
392-
if (updated) {
393-
if (!ranges) ranges = sel.ranges.slice()
394-
ranges[i] = updated
395-
}
396-
}
397-
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel
398-
}
399-
400379
select(event: MouseEvent) {
401-
let {view} = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple))
380+
let {view} = this, selection = skipAtomsForSelection(this.atoms, this.style.get(event, this.extend, this.multiple))
402381
if (this.mustSelect || !selection.eq(view.state.selection, this.dragging === false))
403382
this.view.dispatch({
404383
selection,
@@ -549,6 +528,8 @@ handlers.mousedown = (view, event: MouseEvent) => {
549528
mouseSel.start(event)
550529
return mouseSel.dragging === false
551530
}
531+
} else {
532+
view.inputState.setSelectionOrigin("select.pointer")
552533
}
553534
return false
554535
}

0 commit comments

Comments
 (0)