diff --git a/io/router/key_test.go b/io/router/key_test.go index c3a7510b..b0cd799d 100644 --- a/io/router/key_test.go +++ b/io/router/key_test.go @@ -274,6 +274,7 @@ func TestFocusScroll(t *testing.T) { r := new(Router) h := new(int) + parent := clip.Rect(image.Rect(1, 1, 14, 39)).Push(ops) cl := clip.Rect(image.Rect(10, -20, 20, 30)).Push(ops) key.InputOp{Tag: h}.Add(ops) pointer.InputOp{ @@ -282,12 +283,13 @@ func TestFocusScroll(t *testing.T) { ScrollBounds: image.Rect(-100, -100, 100, 100), }.Add(ops) cl.Pop() + parent.Pop() r.Frame(ops) r.MoveFocus(FocusLeft) r.RevealFocus(image.Rect(0, 0, 15, 40)) evts := r.Events(h) - assertScrollEvent(t, evts[len(evts)-1], f32.Pt(5, -10)) + assertScrollEvent(t, evts[len(evts)-1], f32.Pt(6, -9)) } func TestFocusClick(t *testing.T) { diff --git a/io/router/pointer.go b/io/router/pointer.go index 8ac71456..6c1ce31d 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -845,6 +845,18 @@ func (q *pointerQueue) deliverTransferCancelEvent(p *pointerInfo, events *handle p.dataTarget = nil } +// ClipFor clips r to the parents of area. +func (q *pointerQueue) ClipFor(area int, r image.Rectangle) image.Rectangle { + a := &q.areas[area] + parent := a.parent + for parent != -1 { + a := &q.areas[parent] + r = r.Intersect(a.bounds()) + parent = a.parent + } + return r +} + func searchTag(tags []event.Tag, tag event.Tag) (int, bool) { for i, t := range tags { if t == tag { diff --git a/io/router/router.go b/io/router/router.go index 1fb3788a..3e01ff0d 100644 --- a/io/router/router.go +++ b/io/router/router.go @@ -161,6 +161,8 @@ func (q *Router) RevealFocus(viewport image.Rectangle) { return } bounds := q.key.queue.BoundsFor(focus) + area := q.key.queue.AreaFor(focus) + viewport = q.pointer.queue.ClipFor(area, viewport) topleft := bounds.Min.Sub(viewport.Min) topleft = max(topleft, bounds.Max.Sub(viewport.Max))