Skip to content

Commit

Permalink
Remove composition barrier hack
Browse files Browse the repository at this point in the history
FIX: Remove the workaround that avoided inappropriate styling on composed text after
a decoration again, since it breaks the stock Android virtual keyboard.

Issue codemirror/dev#1358
Issue codemirror/dev#1324
  • Loading branch information
marijnh committed Apr 9, 2024
1 parent 41257cb commit 14772b3
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 38 deletions.
38 changes: 4 additions & 34 deletions src/docview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {ChangeSet, RangeSet, findClusterBreak, SelectionRange} from "@codemirror
import {ContentView, ChildCursor, ViewFlag, DOMPos, replaceRange} from "./contentview"
import {BlockView, LineView, BlockWidgetView} from "./blockview"
import {TextView, MarkView} from "./inlineview"
import {ContentBuilder, NullWidget} from "./buildview"
import {ContentBuilder} from "./buildview"
import browser from "./browser"
import {Decoration, DecorationSet, WidgetType, addRange, MarkDecoration} from "./decoration"
import {getAttrs} from "./attributes"
Expand All @@ -25,11 +25,10 @@ export class DocView extends ContentView {
children!: BlockView[]

decorations: readonly DecorationSet[] = []
dynamicDecorationMap: boolean[] = [false]
dynamicDecorationMap: boolean[] = []
domChanged: {newSel: SelectionRange | null} | null = null
hasComposition: {from: number, to: number} | null = null
markedForComposition: Set<ContentView> = new Set
compositionBarrier = Decoration.none
lastCompositionAfterCursor = false

// Track a minimum width for the editor. When measuring sizes in
Expand Down Expand Up @@ -304,7 +303,7 @@ export class DocView extends ContentView {
// composition, avoid moving it across it and disrupting the
// composition.
suppressWidgetCursorChange(sel: DOMSelectionState, cursor: SelectionRange) {
return this.hasComposition && cursor.empty && !this.compositionBarrier.size &&
return this.hasComposition && cursor.empty &&
isEquivalentPosition(sel.focusNode!, sel.focusOffset, sel.anchorNode, sel.anchorOffset) &&
this.posFromDOM(sel.focusNode!, sel.focusOffset) == cursor.head
}
Expand Down Expand Up @@ -502,7 +501,7 @@ export class DocView extends ContentView {
}

updateDeco() {
let i = 1
let i = 0
let allDeco = this.view.state.facet(decorationsFacet).map(d => {
let dynamic = this.dynamicDecorationMap[i++] = typeof d == "function"
return dynamic ? (d as (view: EditorView) => DecorationSet)(this.view) : d as DecorationSet
Expand All @@ -517,7 +516,6 @@ export class DocView extends ContentView {
allDeco.push(RangeSet.join(outerDeco))
}
this.decorations = [
this.compositionBarrier,
...allDeco,
this.computeBlockGapDeco(),
this.view.viewState.lineGapDeco
Expand All @@ -526,32 +524,6 @@ export class DocView extends ContentView {
return this.decorations
}

// Starting a composition will style the inserted text with the
// style of the text before it, and this is only cleared when the
// composition ends, because touching it before that will abort it.
// This (called from compositionstart handler) tries to notice when
// the cursor is after a non-inclusive mark, where the styling could
// be jarring, and insert an ad-hoc widget before the cursor to
// isolate it from the style before it.
maybeCreateCompositionBarrier() {
let {main: {head, empty}} = this.view.state.selection
if (!empty) return false
let found: boolean | null = null
for (let set of this.decorations) {
set.between(head, head, (from, to, value) => {
if (value.point) found = false
else if (value.endSide < 0 && from < head && to == head) found = true
})
if (found === false) break
}
this.compositionBarrier = found ? Decoration.set(compositionBarrierWidget.range(head)) : Decoration.none
return !!found
}

clearCompositionBarrier() {
this.compositionBarrier = Decoration.none
}

scrollIntoView(target: ScrollTarget) {
if (target.isSnapshot) {
let ref = this.view.viewState.lineBlockAt(target.range.head)
Expand Down Expand Up @@ -589,8 +561,6 @@ export class DocView extends ContentView {
split!: () => ContentView
}

const compositionBarrierWidget = Decoration.widget({side: -1, widget: NullWidget.inline})

function betweenUneditable(pos: DOMPos) {
return pos.node.nodeType == 1 && pos.node.firstChild &&
(pos.offset == 0 || (pos.node.childNodes[pos.offset - 1] as HTMLElement).contentEditable == "false") &&
Expand Down
4 changes: 0 additions & 4 deletions src/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,10 +813,6 @@ observers.compositionstart = observers.compositionupdate = view => {
if (view.inputState.composing < 0) {
// FIXME possibly set a timeout to clear it again on Android
view.inputState.composing = 0
if (view.docView.maybeCreateCompositionBarrier()) {
view.update([])
view.docView.clearCompositionBarrier()
}
}
}

Expand Down

0 comments on commit 14772b3

Please sign in to comment.