Skip to content

Commit

Permalink
When composing, don't move the cursor across zero-len widgets
Browse files Browse the repository at this point in the history
FIX: Fix a composition interruption when an widget is inserted next to the cursor.

Closes codemirror/dev#1310
  • Loading branch information
marijnh committed Dec 19, 2023
1 parent 5cd604e commit eb83b18
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/docview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import browser from "./browser"
import {Decoration, DecorationSet, WidgetType, addRange, MarkDecoration} from "./decoration"
import {getAttrs} from "./attributes"
import {clientRectsFor, isEquivalentPosition, maxOffset, Rect, scrollRectIntoView,
getSelection, hasSelection, textRange} from "./dom"
getSelection, hasSelection, textRange, DOMSelectionState} from "./dom"
import {ViewUpdate, decorations as decorationsFacet,
ChangedRange, ScrollTarget, getScrollMargins} from "./extension"
import {EditorView} from "./editorview"
Expand Down Expand Up @@ -237,9 +237,10 @@ export class DocView extends ContentView {

let domSel = this.view.observer.selectionRange
// If the selection is already here, or in an equivalent position, don't touch it
if (force || !domSel.focusNode ||
!isEquivalentPosition(anchor.node, anchor.offset, domSel.anchorNode, domSel.anchorOffset) ||
!isEquivalentPosition(head.node, head.offset, domSel.focusNode, domSel.focusOffset)) {
if (force || !domSel.focusNode || (
!isEquivalentPosition(anchor.node, anchor.offset, domSel.anchorNode, domSel.anchorOffset) ||
!isEquivalentPosition(head.node, head.offset, domSel.focusNode, domSel.focusOffset)
) && !this.suppressWidgetCursorChange(domSel, main)) {
this.view.observer.ignore(() => {
// Chrome Android will hide the virtual keyboard when tapping
// inside an uneditable node, and not bring it back when we
Expand Down Expand Up @@ -296,6 +297,15 @@ export class DocView extends ContentView {
this.impreciseHead = head.precise ? null: new DOMPos(domSel.focusNode!, domSel.focusOffset)
}

// If a zero-length widget is inserted next to the cursor during
// composition, avoid moving it across it and disrupting the
// composition.
suppressWidgetCursorChange(sel: DOMSelectionState, cursor: SelectionRange) {
return this.hasComposition && cursor.empty &&
isEquivalentPosition(sel.focusNode!, sel.focusOffset, sel.anchorNode, sel.anchorOffset) &&
this.posFromDOM(sel.focusNode!, sel.focusOffset) == cursor.head
}

enforceCursorAssoc() {
if (this.hasComposition) return
let {view} = this, cursor = view.state.selection.main
Expand Down

0 comments on commit eb83b18

Please sign in to comment.