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 <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-01-22 12:56:02 +01:00
parent e70a16c345
commit 24f69bf4bb
5 changed files with 52 additions and 3 deletions
+1 -1
View File
@@ -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 {
+22
View File
@@ -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)
+3 -1
View File
@@ -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
+20
View File
@@ -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
+6 -1
View File
@@ -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
}