Skip to content
This repository was archived by the owner on Apr 15, 2026. It is now read-only.

Commit f22a194

Browse files
committed
Implement iOS selection handle drawing in the selection layer
FIX: Make `drawSelection` draw our own selection handles on iOS. Issue codemirror/dev#1538
1 parent 07d54a0 commit f22a194

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

src/draw-selection.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {EditorSelection, Extension, Facet, combineConfig, Prec, EditorState} fro
22
import {ViewUpdate, nativeSelectionHidden} from "./extension"
33
import {EditorView} from "./editorview"
44
import {layer, RectangleMarker} from "./layer"
5+
import browser from "./browser"
56

67
type SelectionConfig = {
78
/// The length of a full cursor blink cycle, in milliseconds.
@@ -10,13 +11,18 @@ type SelectionConfig = {
1011
/// Whether to show a cursor for non-empty ranges. Defaults to
1112
/// true.
1213
drawRangeCursor?: boolean
14+
/// Because hiding the cursor also hides the selection handles in
15+
/// the iOS browser, when this is enabled (the default), the
16+
/// extension draws handles on the side of the selection in iOS.
17+
iosSelectionHandles?: boolean
1318
}
1419

1520
const selectionConfig = Facet.define<SelectionConfig, Required<SelectionConfig>>({
1621
combine(configs) {
1722
return combineConfig(configs, {
1823
cursorBlinkRate: 1200,
19-
drawRangeCursor: true
24+
drawRangeCursor: true,
25+
iosSelectionHandles: true
2026
}, {
2127
cursorBlinkRate: (a, b) => Math.min(a, b),
2228
drawRangeCursor: (a, b) => a || b
@@ -68,7 +74,7 @@ const cursorLayer = layer({
6874
let cursors = []
6975
for (let r of state.selection.ranges) {
7076
let prim = r == state.selection.main
71-
if (r.empty || conf.drawRangeCursor) {
77+
if (r.empty || conf.drawRangeCursor && !(prim && browser.ios && conf.iosSelectionHandles)) {
7278
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary"
7379
let cursor = r.empty ? r : EditorSelection.cursor(r.head, r.head > r.anchor ? -1 : 1)
7480
for (let piece of RectangleMarker.forRange(view, className, cursor)) cursors.push(piece)
@@ -96,8 +102,19 @@ function setBlinkRate(state: EditorState, dom: HTMLElement) {
96102
const selectionLayer = layer({
97103
above: false,
98104
markers(view) {
99-
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
100-
.reduce((a, b) => a.concat(b))
105+
let markers = [], {main, ranges} = view.state.selection
106+
for (let r of ranges) if (!r.empty) {
107+
for (let marker of RectangleMarker.forRange(view, "cm-selectionBackground", r)) markers.push(marker)
108+
}
109+
if (browser.ios && !main.empty && view.state.facet(selectionConfig).iosSelectionHandles) {
110+
for (let piece of RectangleMarker.forRange(view, "cm-selectionHandle cm-selectionHandle-start",
111+
EditorSelection.cursor(main.from, 1)))
112+
markers.push(piece)
113+
for (let piece of RectangleMarker.forRange(view, "cm-selectionHandle cm-selectionHandle-end",
114+
EditorSelection.cursor(main.to, 1)))
115+
markers.push(piece)
116+
}
117+
return markers
101118
},
102119
update(update, dom) {
103120
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update)

src/theme.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ export const baseTheme = buildTheme("." + baseThemeID, {
133133
"&dark .cm-cursor": {
134134
borderLeftColor: "#ddd"
135135
},
136+
137+
".cm-selectionHandle": {
138+
backgroundColor: "currentColor",
139+
width: "1.5px"
140+
},
141+
".cm-selectionHandle-start::before, .cm-selectionHandle-end::before": {
142+
content: '""',
143+
backgroundColor: "inherit",
144+
borderRadius: "50%",
145+
width: "8px",
146+
height: "8px",
147+
position: "absolute",
148+
left: "-3.25px"
149+
},
150+
".cm-selectionHandle-start::before": {top: "-8px"},
151+
".cm-selectionHandle-end::before": {bottom: "-8px"},
152+
136153
".cm-dropCursor": {
137154
position: "absolute"
138155
},

0 commit comments

Comments
 (0)