diff --git a/gesture/gesture.go b/gesture/gesture.go index 76a0ac36..921440b1 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -43,7 +43,11 @@ func (h *Hover) Add(ops *op.Ops) { // Update state and report whether a pointer is inside the area. func (h *Hover) Update(q input.Source) bool { - for _, ev := range q.Events(h, pointer.Filter{Kinds: pointer.Enter | pointer.Leave}) { + for { + ev, ok := q.Event(h, pointer.Filter{Kinds: pointer.Enter | pointer.Leave}) + if !ok { + break + } e, ok := ev.(pointer.Event) if !ok { continue @@ -172,7 +176,11 @@ func (c *Click) Pressed() bool { // Update state and return the click events. func (c *Click) Update(q input.Source) []ClickEvent { var events []ClickEvent - for _, evt := range q.Events(c, pointer.Filter{Kinds: pointer.Press | pointer.Release | pointer.Enter | pointer.Leave}) { + for { + evt, ok := q.Event(c, pointer.Filter{Kinds: pointer.Press | pointer.Release | pointer.Enter | pointer.Leave}) + if !ok { + break + } e, ok := evt.(pointer.Event) if !ok { continue @@ -261,7 +269,11 @@ func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis, Kinds: pointer.Press | pointer.Drag | pointer.Release | pointer.Scroll, ScrollBounds: bounds, } - for _, evt := range q.Events(s, f) { + for { + evt, ok := q.Event(s, f) + if !ok { + break + } e, ok := evt.(pointer.Event) if !ok { continue @@ -355,8 +367,12 @@ func (d *Drag) Add(ops *op.Ops) { // Update state and return the drag events. func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Event { var events []pointer.Event - for _, e := range q.Events(d, pointer.Filter{Kinds: pointer.Press | pointer.Drag | pointer.Release}) { - e, ok := e.(pointer.Event) + for { + ev, ok := q.Event(d, pointer.Filter{Kinds: pointer.Press | pointer.Drag | pointer.Release}) + if !ok { + break + } + e, ok := ev.(pointer.Event) if !ok { continue } diff --git a/io/input/clipboard_test.go b/io/input/clipboard_test.go index f0020b8b..ca0fcf9d 100644 --- a/io/input/clipboard_test.go +++ b/io/input/clipboard_test.go @@ -28,8 +28,8 @@ func TestClipboardDuplicateEvent(t *testing.T) { }, } router.Queue(event) - assertClipboardEvent(t, router.Events(&handler[0], transfer.TargetFilter{Type: "application/text"}), true) - assertClipboardEvent(t, router.Events(&handler[1], transfer.TargetFilter{Type: "application/text"}), true) + assertClipboardEvent(t, events(router, &handler[0], transfer.TargetFilter{Type: "application/text"}), true) + assertClipboardEvent(t, events(router, &handler[1], transfer.TargetFilter{Type: "application/text"}), true) assertClipboardReadCmd(t, router, 0) ops.Reset() @@ -37,8 +37,8 @@ func TestClipboardDuplicateEvent(t *testing.T) { router.Frame(ops) assertClipboardReadCmd(t, router, 0) - assertClipboardEvent(t, router.Events(&handler[0]), false) - assertClipboardEvent(t, router.Events(&handler[1]), false) + assertClipboardEvent(t, events(router, &handler[0]), false) + assertClipboardEvent(t, events(router, &handler[1]), false) ops.Reset() router.Source().Execute(clipboard.ReadCmd{Tag: &handler[0]}) @@ -46,8 +46,8 @@ func TestClipboardDuplicateEvent(t *testing.T) { router.Frame(ops) // No ClipboardEvent sent assertClipboardReadCmd(t, router, 1) - assertClipboardEvent(t, router.Events(&handler[0]), false) - assertClipboardEvent(t, router.Events(&handler[1]), false) + assertClipboardEvent(t, events(router, &handler[0]), false) + assertClipboardEvent(t, events(router, &handler[1]), false) ops.Reset() } @@ -80,7 +80,7 @@ func TestQueueProcessReadClipboard(t *testing.T) { }, } router.Queue(event) - assertClipboardEvent(t, router.Events(&handler[0], transfer.TargetFilter{Type: "application/text"}), true) + assertClipboardEvent(t, events(router, &handler[0], transfer.TargetFilter{Type: "application/text"}), true) assertClipboardReadCmd(t, router, 0) ops.Reset() @@ -89,7 +89,7 @@ func TestQueueProcessReadClipboard(t *testing.T) { router.Frame(ops) assertClipboardReadCmd(t, router, 0) - assertClipboardEvent(t, router.Events(&handler[0]), false) + assertClipboardEvent(t, events(router, &handler[0]), false) ops.Reset() } diff --git a/io/input/key_test.go b/io/input/key_test.go index 44ac4043..a376ac1d 100644 --- a/io/input/key_test.go +++ b/io/input/key_test.go @@ -22,7 +22,7 @@ func TestInputWakeup(t *testing.T) { var r Router // Test that merely adding a handler doesn't trigger redraw. - evts := r.Events(handler, key.FocusFilter{}) + evts := events(&r, handler, key.FocusFilter{}) r.Frame(&ops) if _, wake := r.WakeupTime(); wake { t.Errorf("adding key.InputOp triggered a redraw") @@ -45,13 +45,13 @@ func TestKeyMultiples(t *testing.T) { event.InputOp(ops, &handlers[2]) for i := range handlers { - assertKeyEvent(t, r.Events(&handlers[i], key.FocusFilter{}), false) + assertKeyEvent(t, events(r, &handlers[i], key.FocusFilter{}), false) } r.Frame(ops) r.Source().Execute(key.FocusCmd{Tag: &handlers[2]}) - assertKeyEvent(t, r.Events(&handlers[2], key.FocusFilter{}), true) + assertKeyEvent(t, events(r, &handlers[2], key.FocusFilter{}), true) assertFocus(t, r, &handlers[2]) assertKeyboard(t, r, TextInputOpen) @@ -72,12 +72,12 @@ func TestKeyStacked(t *testing.T) { event.InputOp(ops, &handlers[3]) for i := range handlers { - assertKeyEvent(t, r.Events(&handlers[i], key.FocusFilter{}), false) + assertKeyEvent(t, events(r, &handlers[i], key.FocusFilter{}), false) } r.Frame(ops) - assertKeyEvent(t, r.Events(&handlers[1], key.FocusFilter{}), true) + assertKeyEvent(t, events(r, &handlers[1], key.FocusFilter{}), true) assertFocus(t, r, &handlers[1]) assertKeyboard(t, r, TextInputOpen) } @@ -114,7 +114,7 @@ func TestKeyRemoveFocus(t *testing.T) { key.Filter{Name: key.NameTab, Required: key.ModShortcut}, } for i := range handlers { - assertKeyEvent(t, r.Events(&handlers[i], filters...), false) + assertKeyEvent(t, events(r, &handlers[i], filters...), false) } r.Frame(ops) @@ -123,7 +123,7 @@ func TestKeyRemoveFocus(t *testing.T) { evt := event.Event(key.Event{Name: key.NameTab, Modifiers: key.ModShortcut, State: key.Press}) r.Queue(evt) - assertKeyEvent(t, r.Events(&handlers[0], filters...), true, evt) + assertKeyEvent(t, events(r, &handlers[0], filters...), true, evt) assertFocus(t, r, &handlers[0]) assertKeyboard(t, r, TextInputOpen) @@ -140,7 +140,7 @@ func TestKeyRemoveFocus(t *testing.T) { r.Frame(ops) - assertKeyEventUnexpected(t, r.Events(&handlers[1], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[1], key.FocusFilter{})) assertFocus(t, r, nil) assertKeyboard(t, r, TextInputClose) @@ -149,8 +149,8 @@ func TestKeyRemoveFocus(t *testing.T) { event.InputOp(ops, &handlers[0]) event.InputOp(ops, &handlers[1]) - assertKeyEventUnexpected(t, r.Events(&handlers[0], key.FocusFilter{})) - assertKeyEventUnexpected(t, r.Events(&handlers[1], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[0], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[1], key.FocusFilter{})) assertFocus(t, r, nil) assertKeyboard(t, r, TextInputClose) @@ -170,7 +170,7 @@ func TestKeyRemoveFocus(t *testing.T) { event.InputOp(ops, &handlers[1]) r.Source().Execute(key.FocusCmd{}) - assertKeyEventUnexpected(t, r.Events(&handlers[1], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[1], key.FocusFilter{})) assertFocus(t, r, nil) assertKeyboard(t, r, TextInputClose) } @@ -189,12 +189,12 @@ func TestKeyFocusedInvisible(t *testing.T) { event.InputOp(ops, &handlers[1]) for i := range handlers { - assertKeyEvent(t, r.Events(&handlers[i], key.FocusFilter{}), false) + assertKeyEvent(t, events(r, &handlers[i], key.FocusFilter{}), false) } r.Frame(ops) - assertKeyEvent(t, r.Events(&handlers[0], key.FocusFilter{}), true) + assertKeyEvent(t, events(r, &handlers[0], key.FocusFilter{}), true) assertFocus(t, r, &handlers[0]) assertKeyboard(t, r, TextInputOpen) @@ -209,8 +209,8 @@ func TestKeyFocusedInvisible(t *testing.T) { r.Frame(ops) - assertKeyEventUnexpected(t, r.Events(&handlers[0], key.FocusFilter{})) - assertKeyEventUnexpected(t, r.Events(&handlers[1], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[0], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[1], key.FocusFilter{})) assertFocus(t, r, nil) assertKeyboard(t, r, TextInputClose) @@ -231,12 +231,12 @@ func TestKeyFocusedInvisible(t *testing.T) { event.InputOp(ops, &handlers[1]) for i := range handlers { - assertKeyEventUnexpected(t, r.Events(&handlers[i], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[i], key.FocusFilter{})) } r.Frame(ops) - assertKeyEventUnexpected(t, r.Events(&handlers[1], key.FocusFilter{})) + assertKeyEventUnexpected(t, events(r, &handlers[1], key.FocusFilter{})) assertFocus(t, r, nil) assertKeyboard(t, r, TextInputClose) } @@ -260,7 +260,7 @@ func TestDirectionalFocus(t *testing.T) { cl := clip.Rect(bounds).Push(ops) event.InputOp(ops, &handlers[i]) cl.Pop() - r.Events(&handlers[i], key.FocusFilter{}) + events(r, &handlers[i], key.FocusFilter{}) } r.Frame(ops) @@ -299,7 +299,7 @@ func TestFocusScroll(t *testing.T) { ScrollBounds: image.Rect(-100, -100, 100, 100), }, } - r.Events(h, filters...) + events(r, h, filters...) parent := clip.Rect(image.Rect(1, 1, 14, 39)).Push(ops) cl := clip.Rect(image.Rect(10, -20, 20, 30)).Push(ops) event.InputOp(ops, h) @@ -311,7 +311,7 @@ func TestFocusScroll(t *testing.T) { r.MoveFocus(key.FocusLeft) r.RevealFocus(image.Rect(0, 0, 15, 40)) - evts := r.Events(h, filters...) + evts := events(r, h, filters...) assertScrollEvent(t, evts[len(evts)-1], f32.Pt(6, -9)) } @@ -326,7 +326,7 @@ func TestFocusClick(t *testing.T) { Kinds: pointer.Press | pointer.Release, }, } - assertEventPointerTypeSequence(t, r.Events(h, filters...), pointer.Cancel) + assertEventPointerTypeSequence(t, events(r, h, filters...), pointer.Cancel) cl := clip.Rect(image.Rect(0, 0, 10, 10)).Push(ops) event.InputOp(ops, h) cl.Pop() @@ -335,7 +335,7 @@ func TestFocusClick(t *testing.T) { r.MoveFocus(key.FocusLeft) r.ClickFocus() - assertEventPointerTypeSequence(t, r.Events(h, filters...), pointer.Press, pointer.Release) + assertEventPointerTypeSequence(t, events(r, h, filters...), pointer.Press, pointer.Release) } func TestNoFocus(t *testing.T) { @@ -372,11 +372,11 @@ func TestKeyRouting(t *testing.T) { key.FocusFilter{}, key.Filter{Name: "B"}, } - r.Events(&handlers[0], fa...) - r.Events(&handlers[1], fb...) - r.Events(&handlers[2], fa...) - r.Events(&handlers[3], key.FocusFilter{}) - r.Events(&handlers[4], fa...) + events(r, &handlers[0], fa...) + events(r, &handlers[1], fb...) + events(r, &handlers[2], fa...) + events(r, &handlers[3], key.FocusFilter{}) + events(r, &handlers[4], fa...) r.Frame(ops) @@ -385,23 +385,23 @@ func TestKeyRouting(t *testing.T) { // With no focus, the events should traverse the final branch of the hit tree // searching for handlers. - if evts := r.Events(&handlers[4], fa...); len(evts) != 1 || evts[0] != A { + if evts := events(r, &handlers[4], fa...); len(evts) != 1 || evts[0] != A { t.Errorf("expected key event") } - r.Events(&handlers[3], key.FocusFilter{}) - r.Events(&handlers[2], fa...) - if evts := r.Events(&handlers[1], fb...); len(evts) != 1 || evts[0] != B { + events(r, &handlers[3], key.FocusFilter{}) + events(r, &handlers[2], fa...) + if evts := events(r, &handlers[1], fb...); len(evts) != 1 || evts[0] != B { t.Errorf("expected key event") } - r.Events(&handlers[0], fa...) + events(r, &handlers[0], fa...) r2 := new(Router) - r2.Events(&handlers[0], fa...) - r2.Events(&handlers[1], fb...) - r2.Events(&handlers[2], fa...) - r2.Events(&handlers[3], key.FocusFilter{}) - r2.Events(&handlers[4], fa...) + events(r2, &handlers[0], fa...) + events(r2, &handlers[1], fb...) + events(r2, &handlers[2], fa...) + events(r2, &handlers[3], key.FocusFilter{}) + events(r2, &handlers[4], fa...) r2.Source().Execute(key.FocusCmd{Tag: &handlers[3]}) r2.Frame(ops) @@ -410,8 +410,8 @@ func TestKeyRouting(t *testing.T) { // With focus, the events should traverse the branch of the hit tree // containing the focused element. - assertKeyEvent(t, r2.Events(&handlers[3], key.FocusFilter{}), true) - if evts := r2.Events(&handlers[0], fa...); len(evts) != 1 || evts[0] != A { + assertKeyEvent(t, events(r2, &handlers[3], key.FocusFilter{}), true) + if evts := events(r2, &handlers[0], fa...); len(evts) != 1 || evts[0] != A { t.Errorf("expected key event") } } diff --git a/io/input/pointer_test.go b/io/input/pointer_test.go index f19d7d74..4b4ecbf8 100644 --- a/io/input/pointer_test.go +++ b/io/input/pointer_test.go @@ -51,7 +51,19 @@ func TestPointerDrag(t *testing.T) { Position: f32.Pt(150, 150), }, ) - assertEventPointerTypeSequence(t, r.Events(handler, f), pointer.Enter, pointer.Press, pointer.Leave, pointer.Drag) + assertEventPointerTypeSequence(t, events(&r, handler, f), pointer.Enter, pointer.Press, pointer.Leave, pointer.Drag) +} + +func events(r *Router, h event.Tag, filters ...event.Filter) []event.Event { + var events []event.Event + for { + e, ok := r.Event(h, filters...) + if !ok { + break + } + events = append(events, e) + } + return events } func TestPointerDragNegative(t *testing.T) { @@ -73,7 +85,7 @@ func TestPointerDragNegative(t *testing.T) { Position: f32.Pt(-150, -150), }, ) - assertEventPointerTypeSequence(t, r.Events(handler, f), pointer.Enter, pointer.Press, pointer.Leave, pointer.Drag) + assertEventPointerTypeSequence(t, events(&r, handler, f), pointer.Enter, pointer.Press, pointer.Leave, pointer.Drag) } func TestPointerGrab(t *testing.T) { @@ -89,9 +101,9 @@ func TestPointerGrab(t *testing.T) { event.InputOp(&ops, handler3) var r Router - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler3, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler3, filter), pointer.Cancel) r.Frame(&ops) r.Queue( pointer.Event{ @@ -99,9 +111,9 @@ func TestPointerGrab(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(handler3, filter), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler3, filter), pointer.Press) r.Source().Execute(pointer.GrabCmd{Tag: handler1}) r.Frame(&ops) r.Queue( @@ -110,9 +122,9 @@ func TestPointerGrab(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Release) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler3, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Release) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler3, filter), pointer.Cancel) } func TestPointerGrabSameHandlerTwice(t *testing.T) { @@ -127,8 +139,8 @@ func TestPointerGrabSameHandlerTwice(t *testing.T) { event.InputOp(&ops, handler2) var r Router - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Cancel) r.Frame(&ops) r.Queue( pointer.Event{ @@ -136,8 +148,8 @@ func TestPointerGrabSameHandlerTwice(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Press) r.Source().Execute(pointer.GrabCmd{Tag: handler1}) r.Frame(&ops) r.Queue( @@ -146,8 +158,8 @@ func TestPointerGrabSameHandlerTwice(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, filter), pointer.Release) - assertEventPointerTypeSequence(t, r.Events(handler2, filter), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, filter), pointer.Release) + assertEventPointerTypeSequence(t, events(&r, handler2, filter), pointer.Cancel) } func TestPointerMove(t *testing.T) { @@ -169,8 +181,8 @@ func TestPointerMove(t *testing.T) { r1.Pop() var r Router - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Cancel) r.Frame(&ops) r.Queue( // Hit both handlers. @@ -192,8 +204,8 @@ func TestPointerMove(t *testing.T) { Kind: pointer.Cancel, }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Enter, pointer.Move, pointer.Move, pointer.Leave, pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Enter, pointer.Move, pointer.Leave, pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Enter, pointer.Move, pointer.Move, pointer.Leave, pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Enter, pointer.Move, pointer.Leave, pointer.Cancel) } func TestPointerTypes(t *testing.T) { @@ -207,7 +219,7 @@ func TestPointerTypes(t *testing.T) { r1.Pop() var r Router - assertEventPointerTypeSequence(t, r.Events(handler, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler, f), pointer.Cancel) r.Frame(&ops) r.Queue( pointer.Event{ @@ -223,7 +235,7 @@ func TestPointerTypes(t *testing.T) { Position: f32.Pt(150, 150), }, ) - assertEventPointerTypeSequence(t, r.Events(handler, f), pointer.Press, pointer.Release) + assertEventPointerTypeSequence(t, events(&r, handler, f), pointer.Press, pointer.Release) } func TestPointerSystemAction(t *testing.T) { @@ -275,7 +287,7 @@ func TestPointerPriority(t *testing.T) { Kinds: pointer.Scroll, ScrollBounds: image.Rectangle{Max: image.Point{X: 100}}, } - r.Events(handler1, f1) + events(&r, handler1, f1) event.InputOp(&ops, handler1) r2 := clip.Rect(image.Rect(0, 0, 100, 50)).Push(&ops) @@ -283,7 +295,7 @@ func TestPointerPriority(t *testing.T) { Kinds: pointer.Scroll, ScrollBounds: image.Rectangle{Max: image.Point{X: 20}}, } - r.Events(handler2, f2) + events(&r, handler2, f2) event.InputOp(&ops, handler2) r2.Pop() r1.Pop() @@ -293,7 +305,7 @@ func TestPointerPriority(t *testing.T) { Kinds: pointer.Scroll, ScrollBounds: image.Rectangle{Min: image.Point{X: -20, Y: -40}}, } - r.Events(handler3, f3) + events(&r, handler3, f3) event.InputOp(&ops, handler3) r3.Pop() @@ -324,9 +336,9 @@ func TestPointerPriority(t *testing.T) { }, ) - hev1 := r.Events(handler1, f1) - hev2 := r.Events(handler2, f2) - hev3 := r.Events(handler3, f3) + hev1 := events(&r, handler1, f1) + hev2 := events(&r, handler2, f2) + hev3 := events(&r, handler3, f3) assertEventPointerTypeSequence(t, hev1, pointer.Scroll, pointer.Scroll) assertEventPointerTypeSequence(t, hev2, pointer.Scroll) assertEventPointerTypeSequence(t, hev3, pointer.Scroll) @@ -362,8 +374,8 @@ func TestPointerEnterLeave(t *testing.T) { // First event for a handler is always a Cancel. // Only handler2 should receive the enter/move events because it is on top // and handler1 is not an ancestor in the hit tree. - assertEventPointerTypeSequence(t, r.Events(handler1, f1)) - assertEventPointerTypeSequence(t, r.Events(handler2, f2), pointer.Enter, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler1, f1)) + assertEventPointerTypeSequence(t, events(&r, handler2, f2), pointer.Enter, pointer.Move) // Leave the second area by moving into the first. r.Queue( @@ -373,8 +385,8 @@ func TestPointerEnterLeave(t *testing.T) { }, ) // The cursor leaves handler2 and enters handler1. - assertEventPointerTypeSequence(t, r.Events(handler1, f1), pointer.Enter, pointer.Move) - assertEventPointerTypeSequence(t, r.Events(handler2, f2), pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler1, f1), pointer.Enter, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler2, f2), pointer.Leave) // Move, but stay within the same hit area. r.Queue( @@ -383,8 +395,8 @@ func TestPointerEnterLeave(t *testing.T) { Position: f32.Pt(40, 40), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f1), pointer.Move) - assertEventPointerTypeSequence(t, r.Events(handler2, f2)) + assertEventPointerTypeSequence(t, events(&r, handler1, f1), pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler2, f2)) // Move outside of both inputs. r.Queue( @@ -393,8 +405,8 @@ func TestPointerEnterLeave(t *testing.T) { Position: f32.Pt(300, 300), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f1), pointer.Leave) - assertEventPointerTypeSequence(t, r.Events(handler2, f2)) + assertEventPointerTypeSequence(t, events(&r, handler1, f1), pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler2, f2)) // Check that a Press event generates Enter Events. r.Queue( @@ -403,8 +415,8 @@ func TestPointerEnterLeave(t *testing.T) { Position: f32.Pt(125, 125), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f1)) - assertEventPointerTypeSequence(t, r.Events(handler2, f2), pointer.Enter, pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler1, f1)) + assertEventPointerTypeSequence(t, events(&r, handler2, f2), pointer.Enter, pointer.Press) // Check that a drag only affects the participating handlers. r.Queue( @@ -419,8 +431,8 @@ func TestPointerEnterLeave(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f1)) - assertEventPointerTypeSequence(t, r.Events(handler2, f2), pointer.Leave, pointer.Drag, pointer.Enter, pointer.Drag) + assertEventPointerTypeSequence(t, events(&r, handler1, f1)) + assertEventPointerTypeSequence(t, events(&r, handler2, f2), pointer.Leave, pointer.Drag, pointer.Enter, pointer.Drag) // Check that a Release event generates Enter/Leave Events. r.Queue( @@ -430,9 +442,9 @@ func TestPointerEnterLeave(t *testing.T) { 25), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f1), pointer.Enter) + assertEventPointerTypeSequence(t, events(&r, handler1, f1), pointer.Enter) // The second handler gets the release event because the press started inside it. - assertEventPointerTypeSequence(t, r.Events(handler2, f2), pointer.Release, pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler2, f2), pointer.Release, pointer.Leave) } func TestMultipleAreas(t *testing.T) { @@ -447,7 +459,7 @@ func TestMultipleAreas(t *testing.T) { event.InputOp(&ops, handler) r1.Pop() - assertEventPointerTypeSequence(t, r.Events(handler, f)) + assertEventPointerTypeSequence(t, events(&r, handler, f)) r.Frame(&ops) // Hit first area, then second area, then both. r.Queue( @@ -464,7 +476,7 @@ func TestMultipleAreas(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler, f), pointer.Enter, pointer.Move, pointer.Move, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler, f), pointer.Enter, pointer.Move, pointer.Move, pointer.Move) } func TestPointerEnterLeaveNested(t *testing.T) { @@ -485,8 +497,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { r1.Pop() var r Router - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Cancel) r.Frame(&ops) // Hit both handlers. r.Queue( @@ -497,8 +509,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { ) // First event for a handler is always a Cancel. // Both handlers should receive the Enter and Move events because handler2 is a child of handler1. - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Enter, pointer.Move) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Enter, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Enter, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Enter, pointer.Move) // Leave the second area by moving into the first. r.Queue( @@ -507,8 +519,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { Position: f32.Pt(20, 20), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Move) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Leave) // Move, but stay within the same hit area. r.Queue( @@ -517,8 +529,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { Position: f32.Pt(10, 10), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Move) - assertEventPointerTypeSequence(t, r.Events(handler2, f)) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler2, f)) // Move outside of both inputs. r.Queue( @@ -527,8 +539,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { Position: f32.Pt(200, 200), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Leave) - assertEventPointerTypeSequence(t, r.Events(handler2, f)) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler2, f)) // Check that a Press event generates Enter Events. r.Queue( @@ -537,8 +549,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { Position: f32.Pt(50, 50), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Enter, pointer.Press) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Enter, pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Enter, pointer.Press) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Enter, pointer.Press) // Check that a Release event generates Enter/Leave Events. r.Queue( @@ -547,8 +559,8 @@ func TestPointerEnterLeaveNested(t *testing.T) { Position: f32.Pt(20, 20), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Release) - assertEventPointerTypeSequence(t, r.Events(handler2, f), pointer.Release, pointer.Leave) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Release) + assertEventPointerTypeSequence(t, events(&r, handler2, f), pointer.Release, pointer.Leave) } func TestPointerActiveInputDisappears(t *testing.T) { @@ -566,7 +578,7 @@ func TestPointerActiveInputDisappears(t *testing.T) { Position: f32.Pt(25, 25), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Enter, pointer.Move) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Enter, pointer.Move) r.Frame(&ops) // Re-render with handler missing. @@ -578,7 +590,7 @@ func TestPointerActiveInputDisappears(t *testing.T) { Position: f32.Pt(25, 25), }, ) - assertEventPointerTypeSequence(t, r.Events(handler1, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, handler1, f), pointer.Cancel) } func TestMultitouch(t *testing.T) { @@ -615,8 +627,8 @@ func TestMultitouch(t *testing.T) { PointerID: p2, }, ) - assertEventPointerTypeSequence(t, r.Events(h1, f1), pointer.Enter, pointer.Press) - assertEventPointerTypeSequence(t, r.Events(h2, f2), pointer.Enter, pointer.Press, pointer.Release) + assertEventPointerTypeSequence(t, events(&r, h1, f1), pointer.Enter, pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h2, f2), pointer.Enter, pointer.Press, pointer.Release) } func TestCursor(t *testing.T) { @@ -733,20 +745,20 @@ func TestPassOp(t *testing.T) { var r Router f := pointer.Filter{Kinds: pointer.Press} - assertEventPointerTypeSequence(t, r.Events(h1, f), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(h2, f), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(h3, f), pointer.Cancel) - assertEventPointerTypeSequence(t, r.Events(h4, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h1, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h2, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h3, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h4, f), pointer.Cancel) r.Frame(&ops) r.Queue( pointer.Event{ Kind: pointer.Press, }, ) - assertEventPointerTypeSequence(t, r.Events(h1, f), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(h2, f), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(h3, f), pointer.Press) - assertEventPointerTypeSequence(t, r.Events(h4, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h1, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h2, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h3, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h4, f), pointer.Press) } func TestAreaPassthrough(t *testing.T) { @@ -759,14 +771,14 @@ func TestAreaPassthrough(t *testing.T) { f := pointer.Filter{ Kinds: pointer.Press, } - assertEventPointerTypeSequence(t, r.Events(h, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h, f), pointer.Cancel) r.Frame(&ops) r.Queue( pointer.Event{ Kind: pointer.Press, }, ) - assertEventPointerTypeSequence(t, r.Events(h, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h, f), pointer.Press) } func TestEllipse(t *testing.T) { @@ -780,7 +792,7 @@ func TestEllipse(t *testing.T) { f := pointer.Filter{ Kinds: pointer.Press, } - assertEventPointerTypeSequence(t, r.Events(h, f), pointer.Cancel) + assertEventPointerTypeSequence(t, events(&r, h, f), pointer.Cancel) r.Frame(&ops) r.Queue( // Outside ellipse. @@ -797,7 +809,7 @@ func TestEllipse(t *testing.T) { Kind: pointer.Press, }, ) - assertEventPointerTypeSequence(t, r.Events(h, f), pointer.Press) + assertEventPointerTypeSequence(t, events(&r, h, f), pointer.Press) } func TestTransfer(t *testing.T) { @@ -805,8 +817,8 @@ func TestTransfer(t *testing.T) { tgtArea := srcArea.Add(image.Pt(40, 0)) setup := func(r *Router, ops *op.Ops, srcType, tgtType string) (src, tgt event.Tag) { src, tgt = new(int), new(int) - r.Events(src, transfer.SourceFilter{Type: srcType}) - r.Events(tgt, transfer.TargetFilter{Type: tgtType}) + events(r, src, transfer.SourceFilter{Type: srcType}) + events(r, tgt, transfer.TargetFilter{Type: tgtType}) srcStack := clip.Rect(srcArea).Push(ops) event.InputOp(ops, src) @@ -835,8 +847,8 @@ func TestTransfer(t *testing.T) { Kind: pointer.Move, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"})) - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"})) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) // Drop. r.Queue( @@ -849,8 +861,8 @@ func TestTransfer(t *testing.T) { Kind: pointer.Release, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "file"}), transfer.CancelEvent{}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "file"}), transfer.CancelEvent{}) }) t.Run("drag with valid and invalid targets", func(t *testing.T) { @@ -858,7 +870,7 @@ func TestTransfer(t *testing.T) { var r Router src, tgt1 := setup(&r, ops, "file", "file") tgt2 := new(int) - r.Events(tgt2, transfer.TargetFilter{Type: "nofile"}) + events(&r, tgt2, transfer.TargetFilter{Type: "nofile"}) stack := clip.Rect(tgtArea).Push(ops) event.InputOp(ops, tgt2) stack.Pop() @@ -874,9 +886,9 @@ func TestTransfer(t *testing.T) { Kind: pointer.Move, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"})) - assertEventSequence(t, r.Events(tgt1, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) - assertEventSequence(t, r.Events(tgt2, transfer.TargetFilter{Type: "nofile"})) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"})) + assertEventSequence(t, events(&r, tgt1, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) + assertEventSequence(t, events(&r, tgt2, transfer.TargetFilter{Type: "nofile"})) }) t.Run("drop on invalid target", func(t *testing.T) { @@ -895,8 +907,8 @@ func TestTransfer(t *testing.T) { Kind: pointer.Move, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"})) - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "nofile"})) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"})) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "nofile"})) // Drop. r.Queue( @@ -905,8 +917,8 @@ func TestTransfer(t *testing.T) { Kind: pointer.Release, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "nofile"})) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "nofile"})) }) t.Run("drop on valid target", func(t *testing.T) { @@ -914,7 +926,7 @@ func TestTransfer(t *testing.T) { var r Router src, tgt := setup(&r, ops, "file", "file") // Make the target also a source. This should have no effect. - r.Events(tgt, transfer.SourceFilter{Type: "file"}) + events(&r, tgt, transfer.SourceFilter{Type: "file"}) r.Frame(ops) // Drag. r.Queue( @@ -927,8 +939,8 @@ func TestTransfer(t *testing.T) { Kind: pointer.Move, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"})) - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"})) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "file"}), transfer.InitiateEvent{}) // Drop. r.Queue( @@ -937,14 +949,14 @@ func TestTransfer(t *testing.T) { Kind: pointer.Release, }, ) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"}), transfer.RequestEvent{Type: "file"}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"}), transfer.RequestEvent{Type: "file"}) // Offer valid type and data. ofr := &offer{data: "hello"} r.Source().Execute(transfer.OfferCmd{Tag: src, Type: "file", Data: ofr}) r.Frame(ops) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) - evs := r.Events(tgt, transfer.TargetFilter{Type: "file"}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) + evs := events(&r, tgt, transfer.TargetFilter{Type: "file"}) if len(evs) != 2 { t.Fatalf("unexpected number of events: %d, want 2", len(evs)) } @@ -971,7 +983,7 @@ func TestTransfer(t *testing.T) { var r Router src, tgt := setup(&r, ops, "file", "file") // Make the target also a source. This should have no effect. - r.Events(tgt, transfer.SourceFilter{Type: "file"}) + events(&r, tgt, transfer.SourceFilter{Type: "file"}) r.Frame(ops) // Drag. r.Queue( @@ -989,13 +1001,13 @@ func TestTransfer(t *testing.T) { }, ) ofr := &offer{data: "hello"} - r.Events(src, transfer.SourceFilter{Type: "file"}) - r.Events(tgt, transfer.TargetFilter{Type: "file"}) + events(&r, src, transfer.SourceFilter{Type: "file"}) + events(&r, tgt, transfer.TargetFilter{Type: "file"}) r.Source().Execute(transfer.OfferCmd{Tag: src, Type: "file", Data: ofr}) r.Frame(ops) - assertEventSequence(t, r.Events(src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) + assertEventSequence(t, events(&r, src, transfer.SourceFilter{Type: "file"}), transfer.CancelEvent{}) // Ignore DataEvent and verify that the next frame closes it as unused. - assertEventSequence(t, r.Events(tgt, transfer.TargetFilter{Type: "file"})[1:], transfer.CancelEvent{}) + assertEventSequence(t, events(&r, tgt, transfer.TargetFilter{Type: "file"})[1:], transfer.CancelEvent{}) r.Frame(ops) if !ofr.closed { t.Error("offer was not closed") @@ -1061,7 +1073,7 @@ func addPointerHandler(r *Router, ops *op.Ops, tag event.Tag, area image.Rectang f := pointer.Filter{ Kinds: pointer.Press | pointer.Release | pointer.Move | pointer.Drag | pointer.Enter | pointer.Leave, } - r.Events(tag, f) + events(r, tag, f) defer clip.Rect(area).Push(ops).Pop() event.InputOp(ops, tag) return f @@ -1178,7 +1190,7 @@ func BenchmarkRouterAdd(b *testing.B) { }, }). Push(&ops) - r.Events(handlers[i], pointer.Filter{Kinds: pointer.Move}) + events(&r, handlers[i], pointer.Filter{Kinds: pointer.Move}) event.InputOp(&ops, handlers[i]) } r.Frame(&ops) diff --git a/io/input/router.go b/io/input/router.go index 54e580b5..545c14ba 100644 --- a/io/input/router.go +++ b/io/input/router.go @@ -176,28 +176,16 @@ func (s Source) Enabled() bool { return s.r != nil } -// Events returns the events for the handler tag that matches one +// Event returns the next event for the handler tag that matches one // or more of filters. -func (s Source) Events(k event.Tag, filters ...event.Filter) []event.Event { +func (s Source) Event(k event.Tag, filters ...event.Filter) (event.Event, bool) { if !s.Enabled() { - return nil + return nil, false } - return s.r.Events(k, filters...) + return s.r.Event(k, filters...) } -func (q *Router) Events(k event.Tag, filters ...event.Filter) []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) { +func (q *Router) Event(k event.Tag, filters ...event.Filter) (event.Event, bool) { h := q.stateFor(k) q.scratchFilter.Reset() // Record handler filters and add reset events. diff --git a/io/input/router_test.go b/io/input/router_test.go index a0e902bd..30929d32 100644 --- a/io/input/router_test.go +++ b/io/input/router_test.go @@ -15,7 +15,7 @@ func TestNoFilterAllocs(t *testing.T) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - s.Events(nil, pointer.Filter{}) + s.Event(nil, pointer.Filter{}) } }) if allocs := b.AllocsPerOp(); allocs != 0 { diff --git a/io/input/semantic_test.go b/io/input/semantic_test.go index 6587ae32..732d58a9 100644 --- a/io/input/semantic_test.go +++ b/io/input/semantic_test.go @@ -84,7 +84,7 @@ func TestSemanticDescription(t *testing.T) { semantic.EnabledOp(false).Add(&ops) semantic.SelectedOp(true).Add(&ops) var r Router - r.Events(h, pointer.Filter{ + events(&r, h, pointer.Filter{ Kinds: pointer.Press | pointer.Release, }) r.Frame(&ops) diff --git a/widget/button.go b/widget/button.go index 6eda1f42..95655e06 100644 --- a/widget/button.go +++ b/widget/button.go @@ -163,7 +163,11 @@ func (b *Clickable) Update(gtx layout.Context) []Click { if b.focused { filters = append(filters, key.Filter{Name: key.NameReturn}, key.Filter{Name: key.NameSpace}) } - for _, e := range gtx.Events(&b.keyTag, filters...) { + for { + e, ok := gtx.Event(&b.keyTag, filters...) + if !ok { + break + } switch e := e.(type) { case key.FocusEvent: b.focused = e.Focus diff --git a/widget/dnd.go b/widget/dnd.go index 1dd1be9b..4a905dd4 100644 --- a/widget/dnd.go +++ b/widget/dnd.go @@ -65,8 +65,12 @@ func (d *Draggable) Update(gtx layout.Context) (mime string, requested bool) { } d.pos = pos - for _, ev := range gtx.Events(&d.handle, transfer.SourceFilter{Type: d.Type}) { - if e, ok := ev.(transfer.RequestEvent); ok { + for { + e, ok := gtx.Event(&d.handle, transfer.SourceFilter{Type: d.Type}) + if !ok { + break + } + if e, ok := e.(transfer.RequestEvent); ok { return e.Type, true } } diff --git a/widget/dnd_test.go b/widget/dnd_test.go index 8165f7a7..d5ec9c90 100644 --- a/widget/dnd_test.go +++ b/widget/dnd_test.go @@ -34,7 +34,7 @@ func TestDraggable(t *testing.T) { stack.Pop() drag.Update(gtx) - r.Events(drag, transfer.TargetFilter{Type: drag.Type}) + r.Event(drag, transfer.TargetFilter{Type: drag.Type}) r.Frame(gtx.Ops) r.Queue( pointer.Event{ @@ -52,21 +52,27 @@ func TestDraggable(t *testing.T) { ) ofr := &offer{data: "hello"} drag.Update(gtx) - r.Events(drag, transfer.TargetFilter{Type: drag.Type}) + r.Event(drag, transfer.TargetFilter{Type: drag.Type}) drag.Offer(gtx, "file", ofr) - r.Frame(gtx.Ops) - evs := r.Events(drag, transfer.TargetFilter{Type: drag.Type}) - if len(evs) != 2 { - t.Fatalf("expected 3 event, got %d", len(evs)) + e, ok := r.Event(drag, transfer.TargetFilter{Type: drag.Type}) + if !ok { + t.Fatalf("expected event") } - ev := evs[0].(transfer.DataEvent) + ev := e.(transfer.DataEvent) if got, want := ev.Type, "file"; got != want { t.Errorf("expected %v; got %v", got, want) } if ofr.closed { t.Error("offer closed prematurely") } + e, ok = r.Event(drag, transfer.TargetFilter{Type: drag.Type}) + if !ok { + t.Fatalf("expected event") + } + if _, ok := e.(transfer.CancelEvent); !ok { + t.Fatalf("expected transfer.CancelEvent event") + } r.Frame(gtx.Ops) if !ofr.closed { t.Error("offer was not closed") diff --git a/widget/editor.go b/widget/editor.go index 08678f96..eff06589 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -380,7 +380,11 @@ func (e *Editor) processKey(gtx layout.Context) { } // adjust keeps track of runes dropped because of MaxLen. var adjust int - for _, ke := range gtx.Events(&e.eventKey, filters...) { + for { + ke, ok := gtx.Event(&e.eventKey, filters...) + if !ok { + break + } e.blinkStart = gtx.Now switch ke := ke.(type) { case key.FocusEvent: diff --git a/widget/enum.go b/widget/enum.go index 1326f1bc..545a18a2 100644 --- a/widget/enum.go +++ b/widget/enum.go @@ -66,7 +66,11 @@ func (e *Enum) Update(gtx layout.Context) bool { if e.focused && e.focus == state.key { filters = append(filters, key.Filter{Name: key.NameReturn}, key.Filter{Name: key.NameSpace}) } - for _, ev := range gtx.Events(&state.tag, filters...) { + for { + ev, ok := gtx.Event(&state.tag, filters...) + if !ok { + break + } switch ev := ev.(type) { case key.FocusEvent: if ev.Focus { diff --git a/widget/example_test.go b/widget/example_test.go index 92ad89e4..c6e16c21 100644 --- a/widget/example_test.go +++ b/widget/example_test.go @@ -109,7 +109,11 @@ func ExampleDraggable_Layout() { ds.Pop() // Check for the received data. - for _, ev := range gtx.Events(&drop, transfer.TargetFilter{Type: mime}) { + for { + ev, ok := gtx.Event(&drop, transfer.TargetFilter{Type: mime}) + if !ok { + break + } switch e := ev.(type) { case transfer.DataEvent: data := e.Open() diff --git a/widget/selectable.go b/widget/selectable.go index 28fbc44b..14497dce 100644 --- a/widget/selectable.go +++ b/widget/selectable.go @@ -319,7 +319,11 @@ func (e *Selectable) processKey(gtx layout.Context) { key.Filter{Name: "A", Required: key.ModShortcut}, ) } - for _, ke := range gtx.Events(e, filters...) { + for { + ke, ok := gtx.Event(e, filters...) + if !ok { + break + } switch ke := ke.(type) { case key.FocusEvent: e.focused = ke.Focus