In the latest main (at least in v0.0.0-20230512135434-8571b25ff7cb), when a parent has focus, key.Events still arrive to children for some reason. This can be tested e.g. by modifying the key-input-tree example from giouiorg/include/files/architecture/main.go by making the second child respond only to "A" presses, like so:
func doKeyTree(ops *op.Ops, q event.Queue) {
// Process events that arrived between the last frame and this one for every tag.
for _, tag := range []*bool{&keyRoot, &keyChild1, &keyChild2} {
for _, ev := range q.Events(tag) {
switch ev := ev.(type) {
case pointer.Event:
switch ev.Type {
case pointer.Release:
// Request focus on this tag if the mouse click ended in our area.
key.FocusOp{Tag: tag}.Add(ops)
}
case key.FocusEvent:
// If this tag is focused, update the focused variable.
if ev.Focus {
focused = tag
} else if focused == tag {
focused = nil
}
case key.Event:
// If we got a key.Event, it means that we are the foremost
// handler for that key (based on the contents of our
// key.InputOp's key.Set).
*tag = ev.State == key.Press
}
}
}
// If nothing is focused, focus the root:
if focused == nil {
key.FocusOp{Tag: &keyRoot}.Add(ops)
key.SoftKeyboardOp{Show: true}.Add(ops)
}
// Confine the rootArea of interest to a 200x200 rectangle.
rootRect := clip.Rect(image.Rect(0, 0, 200, 200))
rootArea := rootRect.Push(ops)
keyDisplayForTag(ops, enterAndSpaceKeys, &keyRoot, rootRect)
// Any clip areas we add before Pop-ing the root area
// are considered its children.
child1Rect := clip.Rect(image.Rect(25, 25, 175, 100))
child1Area := child1Rect.Push(ops)
keyDisplayForTag(ops, spaceKey, &keyChild1, child1Rect)
child1Area.Pop()
child2Rect := clip.Rect(image.Rect(100, 25, 175, 175))
child2Area := child2Rect.Push(ops)
keyDisplayForTag(ops, "A", &keyChild2, child2Rect) // THIS IS THE ONLY LINE I MODIFIED
child2Area.Pop()
rootArea.Pop()
// Now anything we add is _not_ a child of the rootArea.
}
If the large widget (parent widget) has focus, the child 2 still get the "A" presses. This cannot be right.
I replicated the behavior and bisected it to this commit:
28c206fc78c76b1481fc3ed4c28ce3562ce424ba is the first bad commit commit 28c206fc78c76b1481fc3ed4c28ce3562ce424ba Author: Elias Naur <mail@eliasnaur.com> Date: Wed Jul 20 10:37:28 2022 +0200 io/router: try all handlers if a key don't match the focus ancestor tree When a key.InputOp is focused, a key.Event is matched to it and its ancestors. If there is no focus, every handler is matched. This change always matches to every handler, after checking the focus and its ancestors. Signed-off-by: Elias Naur <mail@eliasnaur.com> io/router/key_test.go | 4 ++-- io/router/router.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-)
Reading the commit description, it seems that this behavior is deliberate, but I lack the context on why it was made. ~eliasnaur can you comment on this?
I don't remember the intention, but I suppose the offending change can be reverted now that topmost handlers act as backstops for
key.Event
s which is a better behaviour.FWIW, I can't seem to find this
key-input-tree
example in main.go. What did I miss?
Elias Naur referenced this ticket in commit e3ef98d.
FWIW, I can't seem to find this key-input-tree example in main.go. What did I miss?
It's on the
key-input
branch. I can't publish it because the example doesn't work in the WASM environment. I think the use of aniframe
messes up the way we do keyboard focus or something. There's some related discussion in #415.