io/input,io/pointer: [API] make pointer grab a command

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-10-19 17:32:55 -05:00
parent 676b670119
commit 1bcbaa8137
6 changed files with 50 additions and 53 deletions
+2 -8
View File
@@ -107,7 +107,6 @@ type Drag struct {
pressed bool
pid pointer.ID
start f32.Point
grab bool
}
// Scroll detects scroll gestures and reduces them to
@@ -119,7 +118,6 @@ type Scroll struct {
estimator fling.Extrapolation
flinger fling.Animation
pid pointer.ID
grab bool
last int
// Leftover scroll.
scroll float32
@@ -253,7 +251,6 @@ func (ClickEvent) ImplementsEvent() {}
func (s *Scroll) Add(ops *op.Ops, bounds image.Rectangle) {
oph := pointer.InputOp{
Tag: s,
Grab: s.grab,
Kinds: pointer.Press | pointer.Drag | pointer.Release | pointer.Scroll,
ScrollBounds: bounds,
}
@@ -308,7 +305,6 @@ func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis)
fallthrough
case pointer.Cancel:
s.dragging = false
s.grab = false
case pointer.Scroll:
switch s.axis {
case Horizontal:
@@ -330,7 +326,7 @@ func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis)
if e.Priority < pointer.Grabbed {
slop := cfg.Dp(touchSlop)
if dist := dist; dist >= slop || -slop >= dist {
s.grab = true
q.Queue(pointer.GrabCmd{Tag: s, ID: e.PointerID})
}
} else {
s.last = v
@@ -366,7 +362,6 @@ func (s *Scroll) State() ScrollState {
func (d *Drag) Add(ops *op.Ops) {
pointer.InputOp{
Tag: d,
Grab: d.grab,
Kinds: pointer.Press | pointer.Drag | pointer.Release,
}.Add(ops)
}
@@ -408,7 +403,7 @@ func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Even
diff := e.Position.Sub(d.start)
slop := cfg.Dp(touchSlop)
if diff.X*diff.X+diff.Y*diff.Y > float32(slop*slop) {
d.grab = true
q.Queue(pointer.GrabCmd{Tag: d, ID: e.PointerID})
}
}
case pointer.Release, pointer.Cancel:
@@ -417,7 +412,6 @@ func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Even
continue
}
d.dragging = false
d.grab = false
}
events = append(events, e)
+1 -1
View File
@@ -140,7 +140,7 @@ const (
TypeLinearGradientLen = 1 + 8*2 + 4*2
TypePassLen = 1
TypePopPassLen = 1
TypePointerInputLen = 1 + 1 + 1*2 + 2*4 + 2*4
TypePointerInputLen = 1 + 1*2 + 2*4 + 2*4
TypeSourceLen = 1
TypeTargetLen = 1
TypeKeyInputLen = 1 + 1
+23 -25
View File
@@ -63,10 +63,9 @@ type pointerInfo struct {
}
type pointerHandler struct {
area int
active bool
wantsGrab bool
types pointer.Kind
area int
active bool
types pointer.Kind
// min and max horizontal/vertical scroll
scrollRange image.Rectangle
@@ -269,6 +268,26 @@ func (c *pointerCollector) actionInputOp(act system.Action) {
area.action = act
}
func (q *pointerQueue) grab(req pointer.GrabCmd, events *handlerEvents) {
for _, p := range q.pointers {
if !p.pressed || p.id != req.ID {
continue
}
for i, k2 := range p.handlers {
if k2 == req.Tag {
// Drop other handlers that lost their grab.
dropped := q.scratch[:0]
dropped = append(dropped, p.handlers[:i]...)
dropped = append(dropped, p.handlers[i+1:]...)
for _, tag := range dropped {
q.dropHandler(events, tag)
}
return
}
}
}
}
func (c *pointerCollector) inputOp(op pointer.InputOp, events *handlerEvents) {
areaID := c.currentArea()
area := &c.q.areas[areaID]
@@ -281,7 +300,6 @@ func (c *pointerCollector) inputOp(op pointer.InputOp, events *handlerEvents) {
}
area.semantic.valid = area.semantic.content.gestures != 0
h := c.newHandler(op.Tag, events)
h.wantsGrab = h.wantsGrab || op.Grab
h.types = h.types | op.Kinds
h.scrollRange = op.ScrollBounds
}
@@ -560,7 +578,6 @@ func (q *pointerQueue) reset() {
// Reset handler.
h.active = false
h.area = -1
h.wantsGrab = false
h.types = 0
h.sourceMimes = h.sourceMimes[:0]
h.targetMimes = h.targetMimes[:0]
@@ -596,25 +613,6 @@ func (q *pointerQueue) Frame(events *handlerEvents) {
q.dropHandler(nil, k)
delete(q.handlers, k)
}
if h.wantsGrab {
for _, p := range q.pointers {
if !p.pressed {
continue
}
for i, k2 := range p.handlers {
if k2 == k {
// Drop other handlers that lost their grab.
dropped := q.scratch[:0]
dropped = append(dropped, p.handlers[:i]...)
dropped = append(dropped, p.handlers[i+1:]...)
for _, tag := range dropped {
q.dropHandler(events, tag)
}
break
}
}
}
}
}
for i := range q.pointers {
p := &q.pointers[i]
+4 -2
View File
@@ -86,7 +86,7 @@ func TestPointerGrab(t *testing.T) {
types := pointer.Press | pointer.Release
pointer.InputOp{Tag: handler1, Kinds: types, Grab: true}.Add(&ops)
pointer.InputOp{Tag: handler1, Kinds: types}.Add(&ops)
pointer.InputOp{Tag: handler2, Kinds: types}.Add(&ops)
pointer.InputOp{Tag: handler3, Kinds: types}.Add(&ops)
@@ -98,6 +98,7 @@ func TestPointerGrab(t *testing.T) {
Position: f32.Pt(50, 50),
},
)
r.Source().Queue(pointer.GrabCmd{Tag: handler1})
assertEventPointerTypeSequence(t, r.Events(handler1), pointer.Cancel, pointer.Press)
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
assertEventPointerTypeSequence(t, r.Events(handler3), pointer.Cancel, pointer.Press)
@@ -120,7 +121,7 @@ func TestPointerGrabSameHandlerTwice(t *testing.T) {
types := pointer.Press | pointer.Release
pointer.InputOp{Tag: handler1, Kinds: types, Grab: true}.Add(&ops)
pointer.InputOp{Tag: handler1, Kinds: types}.Add(&ops)
pointer.InputOp{Tag: handler1, Kinds: types}.Add(&ops)
pointer.InputOp{Tag: handler2, Kinds: types}.Add(&ops)
@@ -132,6 +133,7 @@ func TestPointerGrabSameHandlerTwice(t *testing.T) {
Position: f32.Pt(50, 50),
},
)
r.Source().Queue(pointer.GrabCmd{Tag: handler1})
assertEventPointerTypeSequence(t, r.Events(handler1), pointer.Cancel, pointer.Press)
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
r.Frame(&ops)
+7 -6
View File
@@ -226,6 +226,8 @@ func (q *Router) executeCommands() {
q.cqueue.ProcessWriteClipboard(req)
case clipboard.ReadCmd:
q.cqueue.ProcessReadClipboard(req.Tag)
case pointer.GrabCmd:
q.pointer.queue.grab(req, &q.handlers)
}
}
q.commands = nil
@@ -470,16 +472,15 @@ func (q *Router) collect() {
case ops.TypePointerInput:
op := pointer.InputOp{
Tag: encOp.Refs[0].(event.Tag),
Grab: encOp.Data[1] != 0,
Kinds: pointer.Kind(bo.Uint16(encOp.Data[2:])),
Kinds: pointer.Kind(bo.Uint16(encOp.Data[1:])),
ScrollBounds: image.Rectangle{
Min: image.Point{
X: int(int32(bo.Uint32(encOp.Data[4:]))),
Y: int(int32(bo.Uint32(encOp.Data[8:]))),
X: int(int32(bo.Uint32(encOp.Data[3:]))),
Y: int(int32(bo.Uint32(encOp.Data[7:]))),
},
Max: image.Point{
X: int(int32(bo.Uint32(encOp.Data[12:]))),
Y: int(int32(bo.Uint32(encOp.Data[16:]))),
X: int(int32(bo.Uint32(encOp.Data[11:]))),
Y: int(int32(bo.Uint32(encOp.Data[15:]))),
},
},
}
+13 -11
View File
@@ -60,9 +60,6 @@ type PassStack struct {
// events.
type InputOp struct {
Tag event.Tag
// Grab, if set, request that the handler get
// Grabbed priority.
Grab bool
// Kinds is a bitwise-or of event types to receive.
Kinds Kind
// ScrollBounds describe the maximum scrollable distances in both
@@ -73,6 +70,12 @@ type InputOp struct {
ScrollBounds image.Rectangle
}
// GrabCmd requests a pointer grab on the pointer identified by ID.
type GrabCmd struct {
Tag event.Tag
ID ID
}
type ID uint16
// Kind of an Event.
@@ -250,15 +253,12 @@ func (op InputOp) Add(o *op.Ops) {
}
data := ops.Write1(&o.Internal, ops.TypePointerInputLen, op.Tag)
data[0] = byte(ops.TypePointerInput)
if op.Grab {
data[1] = 1
}
bo := binary.LittleEndian
bo.PutUint16(data[2:], uint16(op.Kinds))
bo.PutUint32(data[4:], uint32(op.ScrollBounds.Min.X))
bo.PutUint32(data[8:], uint32(op.ScrollBounds.Min.Y))
bo.PutUint32(data[12:], uint32(op.ScrollBounds.Max.X))
bo.PutUint32(data[16:], uint32(op.ScrollBounds.Max.Y))
bo.PutUint16(data[1:], uint16(op.Kinds))
bo.PutUint32(data[3:], uint32(op.ScrollBounds.Min.X))
bo.PutUint32(data[7:], uint32(op.ScrollBounds.Min.Y))
bo.PutUint32(data[11:], uint32(op.ScrollBounds.Max.X))
bo.PutUint32(data[15:], uint32(op.ScrollBounds.Max.Y))
}
func (t Kind) String() string {
@@ -404,3 +404,5 @@ func (c Cursor) String() string {
}
func (Event) ImplementsEvent() {}
func (GrabCmd) ImplementsCommand() {}