diff --git a/internal/ops/ops.go b/internal/ops/ops.go index ad7f35a9..92ccc5d2 100644 --- a/internal/ops/ops.go +++ b/internal/ops/ops.go @@ -83,7 +83,6 @@ const ( TypeSemanticSelected TypeSemanticEnabled TypeSnippet - TypeSelection TypeActionInput ) @@ -166,7 +165,6 @@ const ( TypeSemanticSelectedLen = 2 TypeSemanticEnabledLen = 2 TypeSnippetLen = 1 + 4 + 4 - TypeSelectionLen = 1 + 2*4 + 2*4 + 4 + 4 TypeActionInputLen = 1 + 1 ) @@ -447,7 +445,6 @@ var opProps = [0x100]opProp{ TypeSemanticSelected: {Size: TypeSemanticSelectedLen, NumRefs: 0}, TypeSemanticEnabled: {Size: TypeSemanticEnabledLen, NumRefs: 0}, TypeSnippet: {Size: TypeSnippetLen, NumRefs: 2}, - TypeSelection: {Size: TypeSelectionLen, NumRefs: 1}, TypeActionInput: {Size: TypeActionInputLen, NumRefs: 0}, } diff --git a/io/input/key.go b/io/input/key.go index 1fae2cd7..07d900ae 100644 --- a/io/input/key.go +++ b/io/input/key.go @@ -42,6 +42,7 @@ type keyHandler struct { order int dirOrder int filter key.Set + trans f32.Affine2D } type dirFocusEntry struct { @@ -290,19 +291,28 @@ func (q *keyQueue) handlerFor(tag event.Tag, area int, bounds image.Rectangle) * return h } -func (q *keyQueue) inputOp(op key.InputOp, area int, bounds image.Rectangle) { +func (q *keyQueue) inputOp(op key.InputOp, t f32.Affine2D, area int, bounds image.Rectangle) { h := q.handlerFor(op.Tag, area, bounds) h.visible = true h.hint = op.Hint h.filter = op.Keys + h.trans = t } -func (q *keyQueue) selectionOp(t f32.Affine2D, op key.SelectionOp) { - if op.Tag == q.focus { - q.content.Selection.Range = op.Range - q.content.Selection.Caret = op.Caret - q.content.Selection.Transform = t +func (q *keyQueue) setSelection(req key.SelectionCmd) { + if req.Tag != q.focus { + return } + q.content.Selection.Range = req.Range + q.content.Selection.Caret = req.Caret +} + +func (q *keyQueue) editorState() EditorState { + s := q.content + if f := q.focus; f != nil { + s.Selection.Transform = q.handlers[f].trans + } + return s } func (q *keyQueue) snippetOp(op key.SnippetOp) { diff --git a/io/input/router.go b/io/input/router.go index 83967e62..dbcc7f18 100644 --- a/io/input/router.go +++ b/io/input/router.go @@ -6,7 +6,6 @@ import ( "encoding/binary" "image" "io" - "math" "strings" "time" @@ -214,6 +213,8 @@ func (q *Router) queue(f Command) { func (q *Router) executeCommands() { for _, req := range q.commands { switch req := req.(type) { + case key.SelectionCmd: + q.key.queue.setSelection(req) case key.FocusCmd: q.key.queue.Focus(req.Tag, &q.handlers) case key.SoftKeyboardCmd: @@ -403,7 +404,7 @@ func (q *Router) AppendSemantics(nodes []SemanticNode) []SemanticNode { // EditorState returns the editor state for the focused handler, or the // zero value if there is none. func (q *Router) EditorState() EditorState { - return q.key.queue.content + return q.key.queue.editorState() } func (q *Router) collect() { @@ -516,7 +517,7 @@ func (q *Router) collect() { a := pc.currentArea() b := pc.currentAreaBounds() pc.keyInputOp(op) - kq.inputOp(op, a, b) + kq.inputOp(op, t, a, b) case ops.TypeSnippet: op := key.SnippetOp{ Tag: encOp.Refs[0].(event.Tag), @@ -529,23 +530,6 @@ func (q *Router) collect() { }, } kq.snippetOp(op) - case ops.TypeSelection: - op := key.SelectionOp{ - Tag: encOp.Refs[0].(event.Tag), - Range: key.Range{ - Start: int(int32(bo.Uint32(encOp.Data[1:]))), - End: int(int32(bo.Uint32(encOp.Data[5:]))), - }, - Caret: key.Caret{ - Pos: f32.Point{ - X: math.Float32frombits(bo.Uint32(encOp.Data[9:])), - Y: math.Float32frombits(bo.Uint32(encOp.Data[13:])), - }, - Ascent: math.Float32frombits(bo.Uint32(encOp.Data[17:])), - Descent: math.Float32frombits(bo.Uint32(encOp.Data[21:])), - }, - } - kq.selectionOp(t, op) // Semantic ops. case ops.TypeSemanticLabel: diff --git a/io/key/key.go b/io/key/key.go index eb24989c..40f27879 100644 --- a/io/key/key.go +++ b/io/key/key.go @@ -11,7 +11,6 @@ package key import ( "encoding/binary" - "math" "strings" "gioui.org/f32" @@ -39,6 +38,13 @@ type SoftKeyboardCmd struct { Show bool } +// SelectionCmd updates the selection for an input handler. +type SelectionCmd struct { + Tag event.Tag + Range + Caret +} + // Set is an expression that describes a set of key combinations, in the form // "-|...". Modifiers are separated by dashes, optional // modifiers are enclosed by parentheses. A key set is either a literal key @@ -55,13 +61,6 @@ type SoftKeyboardCmd struct { // - Shift-(Ctrl)-A matches A if shift is pressed, and optionally ctrl. type Set string -// SelectionOp updates the selection for an input handler. -type SelectionOp struct { - Tag event.Tag - Range - Caret -} - // SnippetOp updates the content snippet for an input handler. type SnippetOp struct { Tag event.Tag @@ -344,18 +343,6 @@ func (s SnippetOp) Add(o *op.Ops) { bo.PutUint32(data[5:], uint32(s.Range.End)) } -func (s SelectionOp) Add(o *op.Ops) { - data := ops.Write1(&o.Internal, ops.TypeSelectionLen, s.Tag) - data[0] = byte(ops.TypeSelection) - bo := binary.LittleEndian - bo.PutUint32(data[1:], uint32(s.Start)) - bo.PutUint32(data[5:], uint32(s.End)) - bo.PutUint32(data[9:], math.Float32bits(s.Pos.X)) - bo.PutUint32(data[13:], math.Float32bits(s.Pos.Y)) - bo.PutUint32(data[17:], math.Float32bits(s.Ascent)) - bo.PutUint32(data[21:], math.Float32bits(s.Descent)) -} - func (EditEvent) ImplementsEvent() {} func (Event) ImplementsEvent() {} func (FocusEvent) ImplementsEvent() {} @@ -364,6 +351,7 @@ func (SelectionEvent) ImplementsEvent() {} func (FocusCmd) ImplementsCommand() {} func (SoftKeyboardCmd) ImplementsCommand() {} +func (SelectionCmd) ImplementsCommand() {} func (m Modifiers) String() string { var strs []string diff --git a/widget/editor.go b/widget/editor.go index b86411cc..df98bad1 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -537,11 +537,7 @@ func (e *Editor) Update(gtx layout.Context) { } if newSel != e.ime.selection { e.ime.selection = newSel - key.SelectionOp{ - Tag: &e.eventKey, - Range: newSel.rng, - Caret: newSel.caret, - }.Add(gtx.Ops) + gtx.Queue(key.SelectionCmd{Tag: &e.eventKey, Range: newSel.rng, Caret: newSel.caret}) } e.updateSnippet(gtx, e.ime.start, e.ime.end)