From 8fb6d3da2b015008ae9debb44241bef13b5c56fb Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 20 Jun 2024 15:21:35 +0200 Subject: [PATCH] io/input: deliver all observed events before deferring the rest Even when a command defers event delivery to the next frame, the already observed events must still be delivered in the current frame. This matters for pointer events that hit more than one event handler. Fixes: https://todo.sr.ht/~eliasnaur/gio/594 Signed-off-by: Elias Naur --- io/input/pointer_test.go | 27 ++++++++++++++++++++++++++ io/input/router.go | 41 ++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 20 deletions(-) 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 } } }