diff --git a/io/router/pointer.go b/io/router/pointer.go index 2361789d..cb30f639 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -321,12 +321,18 @@ func (c *pointerCollector) offerOp(op transfer.OfferOp, events *handlerEvents) { h.data = op.Data } -func (c *pointerCollector) reset(q *pointerQueue) { - q.reset() +func (c *pointerCollector) reset() { + c.q.reset() c.resetState() c.nodeStack = c.nodeStack[:0] - c.q = q - // Add implicit root area for semantic descriptions to hang onto. + c.ensureRoot() +} + +// Ensure implicit root area for semantic descriptions to hang onto. +func (c *pointerCollector) ensureRoot() { + if len(c.q.areas) > 0 { + return + } c.pushArea(areaRect, f32.Rect(-1e6, -1e6, 1e6, 1e6)) // Make it semantic to ensure a single semantic root. c.q.areas[0].semantic.valid = true diff --git a/io/router/router.go b/io/router/router.go index 747fbe7c..a02f0f6f 100644 --- a/io/router/router.go +++ b/io/router/router.go @@ -183,13 +183,16 @@ func (q *Router) SemanticAt(pos f32.Point) (SemanticID, bool) { // AppendSemantics appends the semantic tree to nodes, and returns the result. // The root node is the first added. func (q *Router) AppendSemantics(nodes []SemanticNode) []SemanticNode { + q.pointer.collector.q = &q.pointer.queue + q.pointer.collector.ensureRoot() return q.pointer.queue.AppendSemantics(nodes) } func (q *Router) collect() { q.transStack = q.transStack[:0] pc := &q.pointer.collector - pc.reset(&q.pointer.queue) + pc.q = &q.pointer.queue + pc.reset() kc := &q.key.collector *kc = keyCollector{q: &q.key.queue} q.key.queue.Reset() diff --git a/io/router/semantic_test.go b/io/router/semantic_test.go index 91835c61..71ea8469 100644 --- a/io/router/semantic_test.go +++ b/io/router/semantic_test.go @@ -15,6 +15,14 @@ import ( "gioui.org/op/clip" ) +func TestEmptySemantics(t *testing.T) { + var r Router + tree := r.AppendSemantics(nil) + if len(tree) != 1 { + t.Errorf("expected 1 semantic node for empty tree, got %d", len(tree)) + } +} + func TestSemanticTree(t *testing.T) { var ( ops op.Ops