io/input: switch internal API to return one event at a time

Make the internal changes to support fine-grained event delivery.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-11-24 15:02:31 -06:00
parent fc208248b7
commit bce1dbd654
+33 -23
View File
@@ -124,6 +124,8 @@ type handler struct {
filter filter filter filter
// prevFilter is the filter being built in the current frame. // prevFilter is the filter being built in the current frame.
nextFilter filter nextFilter filter
// processedFilter is the filters that have exhausted available events.
processedFilter filter
} }
// filter is the union of a set of [io/event.Filters]. // filter is the union of a set of [io/event.Filters].
@@ -185,6 +187,17 @@ func (s Source) Events(k event.Tag, filters ...event.Filter) []event.Event {
func (q *Router) Events(k event.Tag, filters ...event.Filter) []event.Event { func (q *Router) Events(k event.Tag, filters ...event.Filter) []event.Event {
var events []event.Event var events []event.Event
for {
e, ok := q.nextEvent(k, filters...)
if !ok {
break
}
events = append(events, e)
}
return events
}
func (q *Router) nextEvent(k event.Tag, filters ...event.Filter) (event.Event, bool) {
h := q.stateFor(k) h := q.stateFor(k)
q.scratchFilter.Reset() q.scratchFilter.Reset()
// Record handler filters and add reset events. // Record handler filters and add reset events.
@@ -193,38 +206,34 @@ func (q *Router) Events(k event.Tag, filters ...event.Filter) []event.Event {
switch f.(type) { switch f.(type) {
case key.FocusFilter: case key.FocusFilter:
if reset, ok := h.key.ResetEvent(); ok { if reset, ok := h.key.ResetEvent(); ok {
events = append(events, reset) return reset, true
} }
case pointer.Filter: case pointer.Filter:
if reset, ok := h.pointer.ResetEvent(); ok { if reset, ok := h.pointer.ResetEvent(); ok {
events = append(events, reset) return reset, true
} }
} }
} }
h.nextFilter.Merge(q.scratchFilter) h.nextFilter.Merge(q.scratchFilter)
if q.deferring { if !q.deferring {
return events for i := range q.changes {
} change := &q.changes[i]
// Accumulate events from state changes until there are no more j := 0
// matching events. for j < len(change.events) {
matchedIdx := 0 evt := change.events[j]
for i := range q.changes { if evt.tag != k || !q.scratchFilter.Matches(evt.event) {
change := &q.changes[i] j++
j := 0 continue
for j < len(change.events) { }
evt := change.events[j] change.events = append(change.events[:j], change.events[j+1:]...)
if evt.tag != k || !q.scratchFilter.Matches(evt.event) { // Fast forward state to last matched.
j++ q.collapseState(i)
continue return evt.event, true
} }
events = append(events, evt.event)
change.events = append(change.events[:j], change.events[j+1:]...)
matchedIdx = i
} }
} }
// Fast forward state to last matched. h.processedFilter.Merge(q.scratchFilter)
q.collapseState(matchedIdx) return nil, false
return events
} }
// collapseState in the interval [1;idx] into q.changes[0]. // collapseState in the interval [1;idx] into q.changes[0].
@@ -269,6 +278,7 @@ func (q *Router) Frame(frame *op.Ops) {
for _, h := range q.handlers { for _, h := range q.handlers {
h.filter, h.nextFilter = h.nextFilter, h.filter h.filter, h.nextFilter = h.nextFilter, h.filter
h.nextFilter.Reset() h.nextFilter.Reset()
h.processedFilter.Reset()
h.pointer.Reset() h.pointer.Reset()
h.key.Reset() h.key.Reset()
} }
@@ -400,7 +410,7 @@ func (q *Router) execute(c Command) {
} }
for _, e := range ch.events { for _, e := range ch.events {
h, ok := q.handlers[e.tag] h, ok := q.handlers[e.tag]
immediate = immediate && ok && h.old && !h.nextFilter.Matches(e.event) immediate = immediate && ok && h.old && !h.processedFilter.Matches(e.event)
} }
if immediate { if immediate {
// Hold on to the remaining events for state replay. // Hold on to the remaining events for state replay.