mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 08:55:35 +00:00
ui: add package input for merged input
To avoid passing a queue type for each kind of input (pointer, key), introduce package input for mapping a handler key to all input events. Future input sources can be added without changes to programs, and as an added bonus, event ordering is preserved across input sources. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+2
-4
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/app/internal/gpu"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/key"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
|
||||
type WindowOptions struct {
|
||||
@@ -238,9 +238,7 @@ func (w *Window) event(e Event) {
|
||||
needAck := false
|
||||
needRedraw := false
|
||||
switch e := e.(type) {
|
||||
case pointer.Event:
|
||||
needRedraw = true
|
||||
case key.Event:
|
||||
case input.Event:
|
||||
needRedraw = true
|
||||
case *Command:
|
||||
needAck = true
|
||||
|
||||
+11
-2
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
|
||||
@@ -80,9 +81,13 @@ func (c *Click) Add(ops *ui.Ops) {
|
||||
op.Add(ops)
|
||||
}
|
||||
|
||||
func (c *Click) Update(q pointer.Events) []ClickEvent {
|
||||
func (c *Click) Update(q input.Events) []ClickEvent {
|
||||
var events []ClickEvent
|
||||
for _, e := range q.For(c) {
|
||||
e, ok := e.(pointer.Event)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch e.Type {
|
||||
case pointer.Release:
|
||||
if c.State == StatePressed {
|
||||
@@ -124,13 +129,17 @@ func (s *Scroll) Dragging() bool {
|
||||
return s.dragging
|
||||
}
|
||||
|
||||
func (s *Scroll) Update(cfg *ui.Config, q pointer.Events, axis Axis) int {
|
||||
func (s *Scroll) Update(cfg *ui.Config, q input.Events, axis Axis) int {
|
||||
if s.axis != axis {
|
||||
s.axis = axis
|
||||
return 0
|
||||
}
|
||||
total := 0
|
||||
for _, e := range q.For(s) {
|
||||
e, ok := e.(pointer.Event)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch e.Type {
|
||||
case pointer.Press:
|
||||
if s.dragging || e.Source != pointer.Touch {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
// Package input exposes a unified interface to input sources. Subpackages
|
||||
// such as pointer and key provide the interfaces for specific input types.
|
||||
package input
|
||||
|
||||
// Events maps an event handler key to the events
|
||||
// available to the handler.
|
||||
type Events interface {
|
||||
For(k Key) []Event
|
||||
}
|
||||
|
||||
// Key is the stable identifier for an event handler. For a handler h, the
|
||||
// key is typically &h.
|
||||
type Key interface{}
|
||||
|
||||
// Event is the marker interface for input events.
|
||||
type Event interface {
|
||||
ImplementsInputEvent()
|
||||
}
|
||||
@@ -1,22 +1,22 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package key
|
||||
package input
|
||||
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/key"
|
||||
)
|
||||
|
||||
type Queue struct {
|
||||
type keyQueue struct {
|
||||
focus Key
|
||||
handlers map[Key]*handler
|
||||
handlers map[Key]*keyHandler
|
||||
reader ui.OpsReader
|
||||
state TextInputState
|
||||
state key.TextInputState
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
type keyHandler struct {
|
||||
active bool
|
||||
events []Event
|
||||
}
|
||||
|
||||
type listenerPriority uint8
|
||||
@@ -30,20 +30,19 @@ const (
|
||||
|
||||
// InputState returns the last text input state as
|
||||
// determined in Frame.
|
||||
func (q *Queue) InputState() TextInputState {
|
||||
func (q *keyQueue) InputState() key.TextInputState {
|
||||
return q.state
|
||||
}
|
||||
|
||||
func (q *Queue) Frame(root *ui.Ops) {
|
||||
func (q *keyQueue) Frame(root *ui.Ops, events handlerEvents) {
|
||||
if q.handlers == nil {
|
||||
q.handlers = make(map[Key]*handler)
|
||||
q.handlers = make(map[Key]*keyHandler)
|
||||
}
|
||||
for _, h := range q.handlers {
|
||||
h.active = false
|
||||
h.events = h.events[:0]
|
||||
}
|
||||
q.reader.Reset(root)
|
||||
focus, pri, hide := q.resolveFocus()
|
||||
focus, pri, hide := q.resolveFocus(events)
|
||||
for k, h := range q.handlers {
|
||||
if !h.active {
|
||||
delete(q.handlers, k)
|
||||
@@ -55,46 +54,33 @@ func (q *Queue) Frame(root *ui.Ops) {
|
||||
changed := focus != nil && focus != q.focus
|
||||
if focus != q.focus {
|
||||
if q.focus != nil {
|
||||
if h, ok := q.handlers[q.focus]; ok {
|
||||
h.events = append(h.events, Focus{Focus: false})
|
||||
}
|
||||
events[q.focus] = append(events[q.focus], key.Focus{Focus: false})
|
||||
}
|
||||
q.focus = focus
|
||||
if q.focus != nil {
|
||||
// A new focus always exists in the handler map.
|
||||
h := q.handlers[q.focus]
|
||||
h.events = append(h.events, Focus{Focus: true})
|
||||
events[q.focus] = append(events[q.focus], key.Focus{Focus: true})
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case pri == priNewFocus:
|
||||
q.state = TextInputOpen
|
||||
q.state = key.TextInputOpen
|
||||
case hide:
|
||||
q.state = TextInputClosed
|
||||
q.state = key.TextInputClosed
|
||||
case changed:
|
||||
q.state = TextInputFocus
|
||||
q.state = key.TextInputFocus
|
||||
default:
|
||||
q.state = TextInputKeep
|
||||
q.state = key.TextInputKeep
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) Push(e Event) {
|
||||
func (q *keyQueue) Push(e Event, events handlerEvents) {
|
||||
if q.focus == nil {
|
||||
return
|
||||
}
|
||||
h := q.handlers[q.focus]
|
||||
h.events = append(h.events, e)
|
||||
events[q.focus] = append(events[q.focus], e)
|
||||
}
|
||||
|
||||
func (q *Queue) For(k Key) []Event {
|
||||
h := q.handlers[k]
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
return h.events
|
||||
}
|
||||
|
||||
func (q *Queue) resolveFocus() (Key, listenerPriority, bool) {
|
||||
func (q *keyQueue) resolveFocus(events handlerEvents) (Key, listenerPriority, bool) {
|
||||
var k Key
|
||||
var pri listenerPriority
|
||||
var hide bool
|
||||
@@ -106,7 +92,7 @@ loop:
|
||||
}
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypeKeyHandler:
|
||||
var op OpHandler
|
||||
var op key.OpHandler
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
var newPri listenerPriority
|
||||
switch {
|
||||
@@ -122,17 +108,16 @@ loop:
|
||||
}
|
||||
h, ok := q.handlers[op.Key]
|
||||
if !ok {
|
||||
h = &handler{
|
||||
// Reset the handler on (each) first appearance.
|
||||
events: []Event{Focus{Focus: false}},
|
||||
}
|
||||
h = new(keyHandler)
|
||||
q.handlers[op.Key] = h
|
||||
// Reset the handler on (each) first appearance.
|
||||
events[op.Key] = []Event{key.Focus{Focus: false}}
|
||||
}
|
||||
h.active = true
|
||||
case ops.TypeHideInput:
|
||||
hide = true
|
||||
case ops.TypePush:
|
||||
newK, newPri, h := q.resolveFocus()
|
||||
newK, newPri, h := q.resolveFocus(events)
|
||||
hide = hide || h
|
||||
if newPri >= pri {
|
||||
k, pri = newK, newPri
|
||||
@@ -1,16 +1,17 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package pointer
|
||||
package input
|
||||
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/f32"
|
||||
"gioui.org/ui/internal/ops"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
|
||||
type Queue struct {
|
||||
type pointerQueue struct {
|
||||
hitTree []hitNode
|
||||
handlers map[Key]*handler
|
||||
handlers map[Key]*pointerHandler
|
||||
pointers []pointerInfo
|
||||
reader ui.OpsReader
|
||||
scratch []Key
|
||||
@@ -25,22 +26,21 @@ type hitNode struct {
|
||||
}
|
||||
|
||||
type pointerInfo struct {
|
||||
id ID
|
||||
id pointer.ID
|
||||
pressed bool
|
||||
handlers []Key
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
type pointerHandler struct {
|
||||
area areaIntersection
|
||||
active bool
|
||||
transform ui.Transform
|
||||
events []Event
|
||||
wantsGrab bool
|
||||
}
|
||||
|
||||
type area struct {
|
||||
trans ui.Transform
|
||||
area OpArea
|
||||
area pointer.OpArea
|
||||
}
|
||||
|
||||
type areaIntersection []area
|
||||
@@ -51,7 +51,7 @@ type areaStack struct {
|
||||
backing []area
|
||||
}
|
||||
|
||||
func (q *Queue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int) {
|
||||
func (q *pointerQueue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int, events handlerEvents) {
|
||||
for {
|
||||
encOp, ok := r.Decode()
|
||||
if !ok {
|
||||
@@ -60,7 +60,7 @@ func (q *Queue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int) {
|
||||
switch ops.OpType(encOp.Data[0]) {
|
||||
case ops.TypePush:
|
||||
q.areas.push()
|
||||
q.collectHandlers(r, t, layer)
|
||||
q.collectHandlers(r, t, layer, events)
|
||||
case ops.TypePop:
|
||||
q.areas.pop()
|
||||
return
|
||||
@@ -68,24 +68,22 @@ func (q *Queue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int) {
|
||||
layer++
|
||||
q.hitTree = append(q.hitTree, hitNode{level: layer})
|
||||
case ops.TypeArea:
|
||||
var op OpArea
|
||||
op.decode(encOp.Data)
|
||||
var op pointer.OpArea
|
||||
op.Decode(encOp.Data)
|
||||
q.areas.add(t, op)
|
||||
case ops.TypeTransform:
|
||||
var op ui.OpTransform
|
||||
op.Decode(encOp.Data)
|
||||
t = t.Mul(op.Transform)
|
||||
case ops.TypePointerHandler:
|
||||
var op OpHandler
|
||||
var op pointer.OpHandler
|
||||
op.Decode(encOp.Data, encOp.Refs)
|
||||
q.hitTree = append(q.hitTree, hitNode{level: layer, key: op.Key})
|
||||
h, ok := q.handlers[op.Key]
|
||||
if !ok {
|
||||
h = &handler{
|
||||
// Reset the handler on (each) first appearance.
|
||||
events: []Event{Event{Type: Cancel}},
|
||||
}
|
||||
h = new(pointerHandler)
|
||||
q.handlers[op.Key] = h
|
||||
events[op.Key] = []Event{pointer.Event{Type: pointer.Cancel}}
|
||||
}
|
||||
h.active = true
|
||||
h.area = q.areas.intersection()
|
||||
@@ -95,7 +93,7 @@ func (q *Queue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) opHit(handlers *[]Key, pos f32.Point) {
|
||||
func (q *pointerQueue) opHit(handlers *[]Key, pos f32.Point) {
|
||||
level := 1 << 30
|
||||
opaque := false
|
||||
for i := len(q.hitTree) - 1; i >= 0; i-- {
|
||||
@@ -114,31 +112,30 @@ func (q *Queue) opHit(handlers *[]Key, pos f32.Point) {
|
||||
continue
|
||||
}
|
||||
res := h.area.hit(pos)
|
||||
opaque = opaque || res == hitOpaque
|
||||
if res != hitNone {
|
||||
opaque = opaque || res == pointer.HitOpaque
|
||||
if res != pointer.HitNone {
|
||||
*handlers = append(*handlers, n.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) init() {
|
||||
func (q *pointerQueue) init() {
|
||||
if q.handlers == nil {
|
||||
q.handlers = make(map[Key]*handler)
|
||||
q.handlers = make(map[Key]*pointerHandler)
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) Frame(root *ui.Ops) {
|
||||
func (q *pointerQueue) Frame(root *ui.Ops, events handlerEvents) {
|
||||
q.init()
|
||||
for _, h := range q.handlers {
|
||||
// Reset handler.
|
||||
h.active = false
|
||||
h.events = h.events[:0]
|
||||
}
|
||||
q.hitTree = q.hitTree[:0]
|
||||
q.areas.reset()
|
||||
q.reader.Reset(root)
|
||||
q.collectHandlers(&q.reader, ui.Transform{}, 0)
|
||||
q.collectHandlers(&q.reader, ui.Transform{}, 0, events)
|
||||
for k, h := range q.handlers {
|
||||
if !h.active {
|
||||
q.dropHandler(k)
|
||||
@@ -146,18 +143,7 @@ func (q *Queue) Frame(root *ui.Ops) {
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) For(k Key) []Event {
|
||||
if k == nil {
|
||||
panic("nil handler")
|
||||
}
|
||||
h := q.handlers[k]
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
return h.events
|
||||
}
|
||||
|
||||
func (q *Queue) dropHandler(k Key) {
|
||||
func (q *pointerQueue) dropHandler(k Key) {
|
||||
delete(q.handlers, k)
|
||||
for i := range q.pointers {
|
||||
p := &q.pointers[i]
|
||||
@@ -169,9 +155,9 @@ func (q *Queue) dropHandler(k Key) {
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) Push(e Event) {
|
||||
func (q *pointerQueue) Push(e pointer.Event, events handlerEvents) {
|
||||
q.init()
|
||||
if e.Type == Cancel {
|
||||
if e.Type == pointer.Cancel {
|
||||
q.pointers = q.pointers[:0]
|
||||
for k := range q.handlers {
|
||||
q.dropHandler(k)
|
||||
@@ -190,7 +176,7 @@ func (q *Queue) Push(e Event) {
|
||||
pidx = len(q.pointers) - 1
|
||||
}
|
||||
p := &q.pointers[pidx]
|
||||
if !p.pressed && (e.Type == Move || e.Type == Press) {
|
||||
if !p.pressed && (e.Type == pointer.Move || e.Type == pointer.Press) {
|
||||
p.handlers, q.scratch = q.scratch[:0], p.handlers
|
||||
q.opHit(&p.handlers, e.Position)
|
||||
// Drop handlers no longer hit.
|
||||
@@ -203,7 +189,7 @@ func (q *Queue) Push(e Event) {
|
||||
}
|
||||
q.dropHandler(h)
|
||||
}
|
||||
if e.Type == Press {
|
||||
if e.Type == pointer.Press {
|
||||
p.pressed = true
|
||||
}
|
||||
}
|
||||
@@ -223,7 +209,7 @@ func (q *Queue) Push(e Event) {
|
||||
q.dropHandler(k)
|
||||
}
|
||||
}
|
||||
if e.Type == Release {
|
||||
if e.Type == pointer.Release {
|
||||
q.pointers = append(q.pointers[:pidx], q.pointers[pidx+1:]...)
|
||||
}
|
||||
for i, k := range p.handlers {
|
||||
@@ -231,14 +217,14 @@ func (q *Queue) Push(e Event) {
|
||||
e := e
|
||||
switch {
|
||||
case p.pressed && len(p.handlers) == 1:
|
||||
e.Priority = Grabbed
|
||||
e.Priority = pointer.Grabbed
|
||||
case i == 0:
|
||||
e.Priority = Foremost
|
||||
e.Priority = pointer.Foremost
|
||||
}
|
||||
e.Hit = h.area.hit(e.Position) != hitNone
|
||||
e.Hit = h.area.hit(e.Position) != pointer.HitNone
|
||||
e.Position = h.transform.InvTransform(e.Position)
|
||||
h.events = append(h.events, e)
|
||||
if e.Type == Release {
|
||||
events[k] = append(events[k], e)
|
||||
if e.Type == pointer.Release {
|
||||
// Release grab when the number of grabs reaches zero.
|
||||
grabs := 0
|
||||
for _, p := range q.pointers {
|
||||
@@ -253,19 +239,19 @@ func (q *Queue) Push(e Event) {
|
||||
}
|
||||
}
|
||||
|
||||
func (a areaIntersection) hit(p f32.Point) hitResult {
|
||||
res := hitNone
|
||||
func (a areaIntersection) hit(p f32.Point) pointer.HitResult {
|
||||
res := pointer.HitNone
|
||||
for _, area := range a {
|
||||
tp := area.trans.InvTransform(p)
|
||||
res = area.area.hit(tp)
|
||||
if res == hitNone {
|
||||
res = area.area.Hit(tp)
|
||||
if res == pointer.HitNone {
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *areaStack) add(t ui.Transform, a OpArea) {
|
||||
func (s *areaStack) add(t ui.Transform, a pointer.OpArea) {
|
||||
s.areas = append(s.areas, area{t, a})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package input
|
||||
|
||||
import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/key"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
|
||||
// Queue is an Events implementation that merges events from
|
||||
// all available input sources.
|
||||
type Queue struct {
|
||||
pqueue pointerQueue
|
||||
kqueue keyQueue
|
||||
|
||||
handlers handlerEvents
|
||||
}
|
||||
|
||||
type handlerEvents map[Key][]Event
|
||||
|
||||
func (q *Queue) For(k Key) []Event {
|
||||
return q.handlers[k]
|
||||
}
|
||||
|
||||
func (q *Queue) Frame(ops *ui.Ops) {
|
||||
q.init()
|
||||
for k := range q.handlers {
|
||||
delete(q.handlers, k)
|
||||
}
|
||||
q.pqueue.Frame(ops, q.handlers)
|
||||
q.kqueue.Frame(ops, q.handlers)
|
||||
}
|
||||
|
||||
func (q *Queue) Add(e Event) {
|
||||
q.init()
|
||||
switch e := e.(type) {
|
||||
case pointer.Event:
|
||||
q.pqueue.Push(e, q.handlers)
|
||||
case key.Edit, key.Chord, key.Focus:
|
||||
q.kqueue.Push(e, q.handlers)
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) InputState() key.TextInputState {
|
||||
return q.kqueue.InputState()
|
||||
}
|
||||
|
||||
func (q *Queue) init() {
|
||||
if q.handlers == nil {
|
||||
q.handlers = make(handlerEvents)
|
||||
}
|
||||
}
|
||||
+6
-14
@@ -16,14 +16,6 @@ type OpHideInput struct{}
|
||||
|
||||
type Key interface{}
|
||||
|
||||
type Events interface {
|
||||
For(k Key) []Event
|
||||
}
|
||||
|
||||
type Event interface {
|
||||
isKeyEvent()
|
||||
}
|
||||
|
||||
type Focus struct {
|
||||
Focus bool
|
||||
}
|
||||
@@ -93,9 +85,9 @@ func (h OpHideInput) Add(o *ui.Ops) {
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
func (Edit) ImplementsEvent() {}
|
||||
func (Chord) ImplementsEvent() {}
|
||||
func (Focus) ImplementsEvent() {}
|
||||
func (Edit) isKeyEvent() {}
|
||||
func (Chord) isKeyEvent() {}
|
||||
func (Focus) isKeyEvent() {}
|
||||
func (Edit) ImplementsEvent() {}
|
||||
func (Chord) ImplementsEvent() {}
|
||||
func (Focus) ImplementsEvent() {}
|
||||
func (Edit) ImplementsInputEvent() {}
|
||||
func (Chord) ImplementsInputEvent() {}
|
||||
func (Focus) ImplementsInputEvent() {}
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/draw"
|
||||
"gioui.org/ui/gesture"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/pointer"
|
||||
)
|
||||
|
||||
@@ -64,7 +65,7 @@ func (l *List) Dragging() bool {
|
||||
return l.scroll.Dragging()
|
||||
}
|
||||
|
||||
func (l *List) Update(c *ui.Config, q pointer.Events) {
|
||||
func (l *List) Update(c *ui.Config, q input.Events) {
|
||||
l.Distance = 0
|
||||
d := l.scroll.Update(c, q, gesture.Axis(l.Axis))
|
||||
l.scrollDir = d
|
||||
|
||||
+12
-15
@@ -37,16 +37,12 @@ type OpHandler struct {
|
||||
|
||||
type Key interface{}
|
||||
|
||||
type Events interface {
|
||||
For(k Key) []Event
|
||||
}
|
||||
|
||||
type hitResult uint8
|
||||
type HitResult uint8
|
||||
|
||||
const (
|
||||
hitNone hitResult = iota
|
||||
hitTransparent
|
||||
hitOpaque
|
||||
HitNone HitResult = iota
|
||||
HitTransparent
|
||||
HitOpaque
|
||||
)
|
||||
|
||||
type ID uint16
|
||||
@@ -103,7 +99,7 @@ func (op OpArea) Add(o *ui.Ops) {
|
||||
o.Write(data)
|
||||
}
|
||||
|
||||
func (op *OpArea) decode(d []byte) {
|
||||
func (op *OpArea) Decode(d []byte) {
|
||||
if ops.OpType(d[0]) != ops.TypeArea {
|
||||
panic("invalid op")
|
||||
}
|
||||
@@ -118,10 +114,10 @@ func (op *OpArea) decode(d []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
func (op *OpArea) hit(pos f32.Point) hitResult {
|
||||
res := hitOpaque
|
||||
func (op *OpArea) Hit(pos f32.Point) HitResult {
|
||||
res := HitOpaque
|
||||
if op.Transparent {
|
||||
res = hitTransparent
|
||||
res = HitTransparent
|
||||
}
|
||||
switch op.kind {
|
||||
case areaRect:
|
||||
@@ -129,7 +125,7 @@ func (op *OpArea) hit(pos f32.Point) hitResult {
|
||||
0 <= pos.Y && pos.Y < float32(op.size.Y) {
|
||||
return res
|
||||
} else {
|
||||
return hitNone
|
||||
return HitNone
|
||||
}
|
||||
case areaEllipse:
|
||||
rx := float32(op.size.X) / 2
|
||||
@@ -141,7 +137,7 @@ func (op *OpArea) hit(pos f32.Point) hitResult {
|
||||
if xh*xh*ry2+yk*yk*rx2 <= rx2*ry2 {
|
||||
return res
|
||||
} else {
|
||||
return hitNone
|
||||
return HitNone
|
||||
}
|
||||
default:
|
||||
panic("invalid area kind")
|
||||
@@ -206,4 +202,5 @@ func (s Source) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (Event) ImplementsEvent() {}
|
||||
func (Event) ImplementsEvent() {}
|
||||
func (Event) ImplementsInputEvent() {}
|
||||
|
||||
+5
-4
@@ -11,6 +11,7 @@ import (
|
||||
"gioui.org/ui"
|
||||
"gioui.org/ui/draw"
|
||||
"gioui.org/ui/gesture"
|
||||
"gioui.org/ui/input"
|
||||
"gioui.org/ui/key"
|
||||
"gioui.org/ui/layout"
|
||||
"gioui.org/ui/pointer"
|
||||
@@ -53,7 +54,7 @@ const (
|
||||
maxBlinkDuration = 10 * time.Second
|
||||
)
|
||||
|
||||
func (e *Editor) Update(c *ui.Config, pq pointer.Events, kq key.Events) {
|
||||
func (e *Editor) Update(c *ui.Config, q input.Events) {
|
||||
if e.cfg == nil || c.PxPerDp != e.cfg.PxPerDp || c.PxPerSp != e.cfg.PxPerSp {
|
||||
e.invalidate()
|
||||
}
|
||||
@@ -68,7 +69,7 @@ func (e *Editor) Update(c *ui.Config, pq pointer.Events, kq key.Events) {
|
||||
axis = gesture.Vertical
|
||||
smin, smax = sbounds.Min.Y, sbounds.Max.Y
|
||||
}
|
||||
sdist := e.scroller.Update(c, pq, axis)
|
||||
sdist := e.scroller.Update(c, q, axis)
|
||||
var soff int
|
||||
if e.SingleLine {
|
||||
e.scrollOff.X += sdist
|
||||
@@ -78,7 +79,7 @@ func (e *Editor) Update(c *ui.Config, pq pointer.Events, kq key.Events) {
|
||||
soff = e.scrollOff.Y
|
||||
}
|
||||
scrollTo := false
|
||||
for _, evt := range e.clicker.Update(pq) {
|
||||
for _, evt := range e.clicker.Update(q) {
|
||||
switch {
|
||||
case evt.Type == gesture.TypePress && evt.Source == pointer.Mouse,
|
||||
evt.Type == gesture.TypeClick && evt.Source == pointer.Touch:
|
||||
@@ -92,7 +93,7 @@ func (e *Editor) Update(c *ui.Config, pq pointer.Events, kq key.Events) {
|
||||
}
|
||||
}
|
||||
stop := (sdist > 0 && soff >= smax) || (sdist < 0 && soff <= smin)
|
||||
for _, ke := range kq.For(e) {
|
||||
for _, ke := range q.For(e) {
|
||||
e.blinkStart = c.Now
|
||||
switch ke := ke.(type) {
|
||||
case key.Focus:
|
||||
|
||||
Reference in New Issue
Block a user