diff --git a/io/router/pointer.go b/io/router/pointer.go index 4e7978a8..24da6482 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -214,7 +214,7 @@ func (q *pointerQueue) opHit(handlers *[]event.Tag, pos f32.Point) { } if n.tag != nil { if _, exists := q.handlers[n.tag]; exists { - *handlers = append(*handlers, n.tag) + *handlers = addHandler(*handlers, n.tag) } } } @@ -473,6 +473,16 @@ func searchTag(tags []event.Tag, tag event.Tag) (int, bool) { return 0, false } +// addHandler adds tag to the slice if not present. +func addHandler(tags []event.Tag, tag event.Tag) []event.Tag { + for _, t := range tags { + if t == tag { + return tags + } + } + return append(tags, tag) +} + func opDecodeFloat32(d []byte) float32 { return float32(int32(binary.LittleEndian.Uint32(d))) } diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index b1228134..f86fec12 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -114,6 +114,38 @@ func TestPointerGrab(t *testing.T) { assertEventSequence(t, r.Events(handler3), pointer.Cancel) } +func TestPointerGrabSameHandlerTwice(t *testing.T) { + handler1 := new(int) + handler2 := new(int) + var ops op.Ops + + types := pointer.Press | pointer.Release + + pointer.InputOp{Tag: handler1, Types: types, Grab: true}.Add(&ops) + pointer.InputOp{Tag: handler1, Types: types}.Add(&ops) + pointer.InputOp{Tag: handler2, Types: types}.Add(&ops) + + var r Router + r.Frame(&ops) + r.Queue( + pointer.Event{ + Type: pointer.Press, + Position: f32.Pt(50, 50), + }, + ) + assertEventSequence(t, r.Events(handler1), pointer.Cancel, pointer.Press) + assertEventSequence(t, r.Events(handler2), pointer.Cancel, pointer.Press) + r.Frame(&ops) + r.Queue( + pointer.Event{ + Type: pointer.Release, + Position: f32.Pt(50, 50), + }, + ) + assertEventSequence(t, r.Events(handler1), pointer.Release) + assertEventSequence(t, r.Events(handler2), pointer.Cancel) +} + func TestPointerMove(t *testing.T) { handler1 := new(int) handler2 := new(int)