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
+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() {}