io: [API] introduce event filters; convert pointer input to use them

Instead of having to supply the predicates for event filtering at the
time of layout, the new Filter type allows widgets to filter at the time
of calling Source.Events. There is then only the need for a single input
op type, in package event.

Filters most importantly allow the use of one tag for several event types,
and we can define that a widget w has &w as its primary tag, by convention.
This allows the replacement of per-widget Focus methods with direct uses
of FocusCmd{&w}, and the later addition of Source.Focused(&w) queries.

Note that the TestCursor test needed restructuring to avoid its use of
InputOps.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-10-16 17:57:27 -05:00
parent d2085ab7c5
commit ef8171b971
19 changed files with 521 additions and 504 deletions
+5 -28
View File
@@ -3,8 +3,6 @@
package pointer
import (
"encoding/binary"
"fmt"
"image"
"strings"
"time"
@@ -56,11 +54,9 @@ type PassStack struct {
macroID uint32
}
// InputOp declares an input handler ready for pointer
// events.
type InputOp struct {
Tag event.Tag
// Kinds is a bitwise-or of event types to receive.
// Filter matches [Event]s.
type Filter struct {
// Kinds is a bitwise-or of event types to match.
Kinds Kind
// ScrollBounds describe the maximum scrollable distances in both
// axes. Specifically, any Event e delivered to Tag will satisfy
@@ -240,27 +236,6 @@ func (op Cursor) Add(o *op.Ops) {
data[1] = byte(op)
}
// Add panics if the scroll range does not contain zero.
func (op InputOp) Add(o *op.Ops) {
if op.Tag == nil {
panic("Tag must be non-nil")
}
if b := op.ScrollBounds; b.Min.X > 0 || b.Max.X < 0 || b.Min.Y > 0 || b.Max.Y < 0 {
panic(fmt.Errorf("invalid scroll range value %v", b))
}
if op.Kinds>>16 > 0 {
panic(fmt.Errorf("value in Types overflows uint16"))
}
data := ops.Write1(&o.Internal, ops.TypePointerInputLen, op.Tag)
data[0] = byte(ops.TypePointerInput)
bo := binary.LittleEndian
bo.PutUint16(data[1:], uint16(op.Kinds))
bo.PutUint32(data[3:], uint32(op.ScrollBounds.Min.X))
bo.PutUint32(data[7:], uint32(op.ScrollBounds.Min.Y))
bo.PutUint32(data[11:], uint32(op.ScrollBounds.Max.X))
bo.PutUint32(data[15:], uint32(op.ScrollBounds.Max.Y))
}
func (t Kind) String() string {
if t == Cancel {
return "Cancel"
@@ -406,3 +381,5 @@ func (c Cursor) String() string {
func (Event) ImplementsEvent() {}
func (GrabCmd) ImplementsCommand() {}
func (Filter) ImplementsFilter() {}