forked from joejulian/gio
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 <mail@eliasnaur.com>
This commit is contained in:
@@ -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
|
||||
|
||||
+21
-20
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user