From 24f69bf4bb9fbfff01de9bbe04333d86a5c55df9 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 22 Jan 2021 12:56:02 +0100 Subject: [PATCH] io/router: don't trigger redraw for handler reset events key.InputOp and pointer.InputOp handlers are reset on first registration through a key.FocusEvent{false} or pointer.Cancel, respectively. However, the mere act of registering a handle shouldn't result in a redraw. This is particularly true for misconfigured handlers where a new tag is supplied every frame, resulting in continously redrawing. Signed-off-by: Elias Naur --- io/router/key.go | 2 +- io/router/key_test.go | 22 ++++++++++++++++++++++ io/router/pointer.go | 4 +++- io/router/pointer_test.go | 20 ++++++++++++++++++++ io/router/router.go | 7 ++++++- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/io/router/key.go b/io/router/key.go index 8d75bb02..d1fbb665 100644 --- a/io/router/key.go +++ b/io/router/key.go @@ -58,7 +58,7 @@ func (q *keyQueue) Frame(root *op.Ops, events *handlerEvents) { } } else if h.new && k != focus { // Reset the handler on (each) first appearance, but don't trigger redraw. - events.Add(k, key.FocusEvent{Focus: false}) + events.AddNoRedraw(k, key.FocusEvent{Focus: false}) } } if changed && focus != nil { diff --git a/io/router/key_test.go b/io/router/key_test.go index bcdc677b..6edd0374 100644 --- a/io/router/key_test.go +++ b/io/router/key_test.go @@ -11,6 +11,28 @@ import ( "gioui.org/op" ) +func TestKeyWakeup(t *testing.T) { + handler := new(int) + var ops op.Ops + key.InputOp{Tag: handler}.Add(&ops) + + var r Router + // Test that merely adding a handler doesn't trigger redraw. + r.Frame(&ops) + if _, wake := r.WakeupTime(); wake { + t.Errorf("adding key.InputOp triggered a redraw") + } + // However, adding a handler queues a Focus(false) event. + if evts := r.Events(handler); len(evts) != 1 { + t.Errorf("no Focus event for newly registered key.InputOp") + } + // Verify that r.Events does trigger a redraw. + r.Frame(&ops) + if _, wake := r.WakeupTime(); !wake { + t.Errorf("key.FocusEvent event didn't trigger a redraw") + } +} + func TestKeyMultiples(t *testing.T) { handlers := make([]int, 3) ops := new(op.Ops) diff --git a/io/router/pointer.go b/io/router/pointer.go index 0fb2b22e..77165429 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -145,7 +145,9 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents) { if !ok { h = new(pointerHandler) q.handlers[op.Tag] = h - events.Add(op.Tag, pointer.Event{Type: pointer.Cancel}) + // Cancel handlers on (each) first appearance, but don't + // trigger redraw. + events.AddNoRedraw(op.Tag, pointer.Event{Type: pointer.Cancel}) } h.active = true h.area = state.area diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index 5acc5c2e..88bb1dcc 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -15,6 +15,26 @@ import ( "gioui.org/op" ) +func TestPointerWakeup(t *testing.T) { + handler := new(int) + var ops op.Ops + addPointerHandler(&ops, handler, image.Rect(0, 0, 100, 100)) + + var r Router + // Test that merely adding a handler doesn't trigger redraw. + r.Frame(&ops) + if _, wake := r.WakeupTime(); wake { + t.Errorf("adding pointer.InputOp triggered a redraw") + } + // However, adding a handler queues a Cancel event. + assertEventSequence(t, r.Events(handler), pointer.Cancel) + // Verify that r.Events does trigger a redraw. + r.Frame(&ops) + if _, wake := r.WakeupTime(); !wake { + t.Errorf("pointer.Cancel event didn't trigger a redraw") + } +} + func TestPointerDrag(t *testing.T) { handler := new(int) var ops op.Ops diff --git a/io/router/router.go b/io/router/router.go index 5b42cfad..46442685 100644 --- a/io/router/router.go +++ b/io/router/router.go @@ -79,6 +79,7 @@ func (q *Router) Frame(ops *op.Ops) { } } +// Add an event and report whether at least one handler had an event queued. func (q *Router) Add(events ...event.Event) bool { for _, e := range events { switch e := e.(type) { @@ -159,9 +160,13 @@ func (h *handlerEvents) init() { } } -func (h *handlerEvents) Add(k event.Tag, e event.Event) { +func (h *handlerEvents) AddNoRedraw(k event.Tag, e event.Event) { h.init() h.handlers[k] = append(h.handlers[k], e) +} + +func (h *handlerEvents) Add(k event.Tag, e event.Event) { + h.AddNoRedraw(k, e) h.hadEvents = true }