mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
io/input,io/pointer: [API] make pointer grab a command
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+2
-8
@@ -107,7 +107,6 @@ type Drag struct {
|
|||||||
pressed bool
|
pressed bool
|
||||||
pid pointer.ID
|
pid pointer.ID
|
||||||
start f32.Point
|
start f32.Point
|
||||||
grab bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll detects scroll gestures and reduces them to
|
// Scroll detects scroll gestures and reduces them to
|
||||||
@@ -119,7 +118,6 @@ type Scroll struct {
|
|||||||
estimator fling.Extrapolation
|
estimator fling.Extrapolation
|
||||||
flinger fling.Animation
|
flinger fling.Animation
|
||||||
pid pointer.ID
|
pid pointer.ID
|
||||||
grab bool
|
|
||||||
last int
|
last int
|
||||||
// Leftover scroll.
|
// Leftover scroll.
|
||||||
scroll float32
|
scroll float32
|
||||||
@@ -253,7 +251,6 @@ func (ClickEvent) ImplementsEvent() {}
|
|||||||
func (s *Scroll) Add(ops *op.Ops, bounds image.Rectangle) {
|
func (s *Scroll) Add(ops *op.Ops, bounds image.Rectangle) {
|
||||||
oph := pointer.InputOp{
|
oph := pointer.InputOp{
|
||||||
Tag: s,
|
Tag: s,
|
||||||
Grab: s.grab,
|
|
||||||
Kinds: pointer.Press | pointer.Drag | pointer.Release | pointer.Scroll,
|
Kinds: pointer.Press | pointer.Drag | pointer.Release | pointer.Scroll,
|
||||||
ScrollBounds: bounds,
|
ScrollBounds: bounds,
|
||||||
}
|
}
|
||||||
@@ -308,7 +305,6 @@ func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis)
|
|||||||
fallthrough
|
fallthrough
|
||||||
case pointer.Cancel:
|
case pointer.Cancel:
|
||||||
s.dragging = false
|
s.dragging = false
|
||||||
s.grab = false
|
|
||||||
case pointer.Scroll:
|
case pointer.Scroll:
|
||||||
switch s.axis {
|
switch s.axis {
|
||||||
case Horizontal:
|
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 {
|
if e.Priority < pointer.Grabbed {
|
||||||
slop := cfg.Dp(touchSlop)
|
slop := cfg.Dp(touchSlop)
|
||||||
if dist := dist; dist >= slop || -slop >= dist {
|
if dist := dist; dist >= slop || -slop >= dist {
|
||||||
s.grab = true
|
q.Queue(pointer.GrabCmd{Tag: s, ID: e.PointerID})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.last = v
|
s.last = v
|
||||||
@@ -366,7 +362,6 @@ func (s *Scroll) State() ScrollState {
|
|||||||
func (d *Drag) Add(ops *op.Ops) {
|
func (d *Drag) Add(ops *op.Ops) {
|
||||||
pointer.InputOp{
|
pointer.InputOp{
|
||||||
Tag: d,
|
Tag: d,
|
||||||
Grab: d.grab,
|
|
||||||
Kinds: pointer.Press | pointer.Drag | pointer.Release,
|
Kinds: pointer.Press | pointer.Drag | pointer.Release,
|
||||||
}.Add(ops)
|
}.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)
|
diff := e.Position.Sub(d.start)
|
||||||
slop := cfg.Dp(touchSlop)
|
slop := cfg.Dp(touchSlop)
|
||||||
if diff.X*diff.X+diff.Y*diff.Y > float32(slop*slop) {
|
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:
|
case pointer.Release, pointer.Cancel:
|
||||||
@@ -417,7 +412,6 @@ func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Even
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
d.dragging = false
|
d.dragging = false
|
||||||
d.grab = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
events = append(events, e)
|
events = append(events, e)
|
||||||
|
|||||||
+1
-1
@@ -140,7 +140,7 @@ const (
|
|||||||
TypeLinearGradientLen = 1 + 8*2 + 4*2
|
TypeLinearGradientLen = 1 + 8*2 + 4*2
|
||||||
TypePassLen = 1
|
TypePassLen = 1
|
||||||
TypePopPassLen = 1
|
TypePopPassLen = 1
|
||||||
TypePointerInputLen = 1 + 1 + 1*2 + 2*4 + 2*4
|
TypePointerInputLen = 1 + 1*2 + 2*4 + 2*4
|
||||||
TypeSourceLen = 1
|
TypeSourceLen = 1
|
||||||
TypeTargetLen = 1
|
TypeTargetLen = 1
|
||||||
TypeKeyInputLen = 1 + 1
|
TypeKeyInputLen = 1 + 1
|
||||||
|
|||||||
+23
-25
@@ -63,10 +63,9 @@ type pointerInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pointerHandler struct {
|
type pointerHandler struct {
|
||||||
area int
|
area int
|
||||||
active bool
|
active bool
|
||||||
wantsGrab bool
|
types pointer.Kind
|
||||||
types pointer.Kind
|
|
||||||
// min and max horizontal/vertical scroll
|
// min and max horizontal/vertical scroll
|
||||||
scrollRange image.Rectangle
|
scrollRange image.Rectangle
|
||||||
|
|
||||||
@@ -269,6 +268,26 @@ func (c *pointerCollector) actionInputOp(act system.Action) {
|
|||||||
area.action = act
|
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) {
|
func (c *pointerCollector) inputOp(op pointer.InputOp, events *handlerEvents) {
|
||||||
areaID := c.currentArea()
|
areaID := c.currentArea()
|
||||||
area := &c.q.areas[areaID]
|
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
|
area.semantic.valid = area.semantic.content.gestures != 0
|
||||||
h := c.newHandler(op.Tag, events)
|
h := c.newHandler(op.Tag, events)
|
||||||
h.wantsGrab = h.wantsGrab || op.Grab
|
|
||||||
h.types = h.types | op.Kinds
|
h.types = h.types | op.Kinds
|
||||||
h.scrollRange = op.ScrollBounds
|
h.scrollRange = op.ScrollBounds
|
||||||
}
|
}
|
||||||
@@ -560,7 +578,6 @@ func (q *pointerQueue) reset() {
|
|||||||
// Reset handler.
|
// Reset handler.
|
||||||
h.active = false
|
h.active = false
|
||||||
h.area = -1
|
h.area = -1
|
||||||
h.wantsGrab = false
|
|
||||||
h.types = 0
|
h.types = 0
|
||||||
h.sourceMimes = h.sourceMimes[:0]
|
h.sourceMimes = h.sourceMimes[:0]
|
||||||
h.targetMimes = h.targetMimes[:0]
|
h.targetMimes = h.targetMimes[:0]
|
||||||
@@ -596,25 +613,6 @@ func (q *pointerQueue) Frame(events *handlerEvents) {
|
|||||||
q.dropHandler(nil, k)
|
q.dropHandler(nil, k)
|
||||||
delete(q.handlers, 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 {
|
for i := range q.pointers {
|
||||||
p := &q.pointers[i]
|
p := &q.pointers[i]
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func TestPointerGrab(t *testing.T) {
|
|||||||
|
|
||||||
types := pointer.Press | pointer.Release
|
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: handler2, Kinds: types}.Add(&ops)
|
||||||
pointer.InputOp{Tag: handler3, 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),
|
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(handler1), pointer.Cancel, pointer.Press)
|
||||||
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
|
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
|
||||||
assertEventPointerTypeSequence(t, r.Events(handler3), 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
|
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: handler1, Kinds: types}.Add(&ops)
|
||||||
pointer.InputOp{Tag: handler2, 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),
|
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(handler1), pointer.Cancel, pointer.Press)
|
||||||
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
|
assertEventPointerTypeSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press)
|
||||||
r.Frame(&ops)
|
r.Frame(&ops)
|
||||||
|
|||||||
+7
-6
@@ -226,6 +226,8 @@ func (q *Router) executeCommands() {
|
|||||||
q.cqueue.ProcessWriteClipboard(req)
|
q.cqueue.ProcessWriteClipboard(req)
|
||||||
case clipboard.ReadCmd:
|
case clipboard.ReadCmd:
|
||||||
q.cqueue.ProcessReadClipboard(req.Tag)
|
q.cqueue.ProcessReadClipboard(req.Tag)
|
||||||
|
case pointer.GrabCmd:
|
||||||
|
q.pointer.queue.grab(req, &q.handlers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
q.commands = nil
|
q.commands = nil
|
||||||
@@ -470,16 +472,15 @@ func (q *Router) collect() {
|
|||||||
case ops.TypePointerInput:
|
case ops.TypePointerInput:
|
||||||
op := pointer.InputOp{
|
op := pointer.InputOp{
|
||||||
Tag: encOp.Refs[0].(event.Tag),
|
Tag: encOp.Refs[0].(event.Tag),
|
||||||
Grab: encOp.Data[1] != 0,
|
Kinds: pointer.Kind(bo.Uint16(encOp.Data[1:])),
|
||||||
Kinds: pointer.Kind(bo.Uint16(encOp.Data[2:])),
|
|
||||||
ScrollBounds: image.Rectangle{
|
ScrollBounds: image.Rectangle{
|
||||||
Min: image.Point{
|
Min: image.Point{
|
||||||
X: int(int32(bo.Uint32(encOp.Data[4:]))),
|
X: int(int32(bo.Uint32(encOp.Data[3:]))),
|
||||||
Y: int(int32(bo.Uint32(encOp.Data[8:]))),
|
Y: int(int32(bo.Uint32(encOp.Data[7:]))),
|
||||||
},
|
},
|
||||||
Max: image.Point{
|
Max: image.Point{
|
||||||
X: int(int32(bo.Uint32(encOp.Data[12:]))),
|
X: int(int32(bo.Uint32(encOp.Data[11:]))),
|
||||||
Y: int(int32(bo.Uint32(encOp.Data[16:]))),
|
Y: int(int32(bo.Uint32(encOp.Data[15:]))),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-11
@@ -60,9 +60,6 @@ type PassStack struct {
|
|||||||
// events.
|
// events.
|
||||||
type InputOp struct {
|
type InputOp struct {
|
||||||
Tag event.Tag
|
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 is a bitwise-or of event types to receive.
|
||||||
Kinds Kind
|
Kinds Kind
|
||||||
// ScrollBounds describe the maximum scrollable distances in both
|
// ScrollBounds describe the maximum scrollable distances in both
|
||||||
@@ -73,6 +70,12 @@ type InputOp struct {
|
|||||||
ScrollBounds image.Rectangle
|
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
|
type ID uint16
|
||||||
|
|
||||||
// Kind of an Event.
|
// 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 := ops.Write1(&o.Internal, ops.TypePointerInputLen, op.Tag)
|
||||||
data[0] = byte(ops.TypePointerInput)
|
data[0] = byte(ops.TypePointerInput)
|
||||||
if op.Grab {
|
|
||||||
data[1] = 1
|
|
||||||
}
|
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
bo.PutUint16(data[2:], uint16(op.Kinds))
|
bo.PutUint16(data[1:], uint16(op.Kinds))
|
||||||
bo.PutUint32(data[4:], uint32(op.ScrollBounds.Min.X))
|
bo.PutUint32(data[3:], uint32(op.ScrollBounds.Min.X))
|
||||||
bo.PutUint32(data[8:], uint32(op.ScrollBounds.Min.Y))
|
bo.PutUint32(data[7:], uint32(op.ScrollBounds.Min.Y))
|
||||||
bo.PutUint32(data[12:], uint32(op.ScrollBounds.Max.X))
|
bo.PutUint32(data[11:], uint32(op.ScrollBounds.Max.X))
|
||||||
bo.PutUint32(data[16:], uint32(op.ScrollBounds.Max.Y))
|
bo.PutUint32(data[15:], uint32(op.ScrollBounds.Max.Y))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Kind) String() string {
|
func (t Kind) String() string {
|
||||||
@@ -404,3 +404,5 @@ func (c Cursor) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (Event) ImplementsEvent() {}
|
func (Event) ImplementsEvent() {}
|
||||||
|
|
||||||
|
func (GrabCmd) ImplementsCommand() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user