diff --git a/io/input/pointer_test.go b/io/input/pointer_test.go index 4d9e2505..ed3bb74a 100644 --- a/io/input/pointer_test.go +++ b/io/input/pointer_test.go @@ -1086,6 +1086,33 @@ func TestPassCursor(t *testing.T) { } } +func TestPartialEvent(t *testing.T) { + var ops op.Ops + var r Router + + rect := clip.Rect(image.Rect(0, 0, 100, 100)) + background := rect.Push(&ops) + event.Op(&ops, 1) + background.Pop() + + overlayPass := pointer.PassOp{}.Push(&ops) + overlay := rect.Push(&ops) + event.Op(&ops, 2) + overlay.Pop() + overlayPass.Pop() + assertEventSequence(t, events(&r, -1, pointer.Filter{Target: 1, Kinds: pointer.Press})) + assertEventSequence(t, events(&r, -1, pointer.Filter{Target: 2, Kinds: pointer.Press})) + r.Frame(&ops) + r.Queue(pointer.Event{ + Kind: pointer.Press, + }) + assertEventSequence(t, events(&r, -1, pointer.Filter{Target: 1, Kinds: pointer.Press}, key.FocusFilter{Target: 1}), + key.FocusEvent{}, pointer.Event{Kind: pointer.Press, Source: pointer.Mouse, Priority: pointer.Shared}) + r.Source().Execute(key.FocusCmd{Tag: 1}) + assertEventSequence(t, events(&r, -1, pointer.Filter{Target: 2, Kinds: pointer.Press}), + pointer.Event{Kind: pointer.Press, Source: pointer.Mouse, Priority: pointer.Foremost}) +} + // offer satisfies io.ReadCloser for use in data transfers. type offer struct { data string diff --git a/io/input/router.go b/io/input/router.go index 5e6b6865..accb37ff 100644 --- a/io/input/router.go +++ b/io/input/router.go @@ -274,28 +274,29 @@ func (q *Router) Event(filters ...event.Filter) (event.Event, bool) { } } } - if !q.deferring { - for i := range q.changes { - change := &q.changes[i] - for j, evt := range change.events { - match := false - switch e := evt.event.(type) { - case key.Event: - match = q.key.scratchFilter.Matches(change.state.keyState.focus, e, false) - default: - for _, tf := range q.scratchFilters { - if evt.tag == tf.tag && tf.filter.Matches(evt.event) { - match = true - break - } + for i := range q.changes { + if q.deferring && i > 0 { + break + } + change := &q.changes[i] + for j, evt := range change.events { + match := false + switch e := evt.event.(type) { + case key.Event: + match = q.key.scratchFilter.Matches(change.state.keyState.focus, e, false) + default: + for _, tf := range q.scratchFilters { + if evt.tag == tf.tag && tf.filter.Matches(evt.event) { + match = true + break } } - if match { - change.events = append(change.events[:j], change.events[j+1:]...) - // Fast forward state to last matched. - q.collapseState(i) - return evt.event, true - } + } + if match { + change.events = append(change.events[:j], change.events[j+1:]...) + // Fast forward state to last matched. + q.collapseState(i) + return evt.event, true } } }