From e17bdfc6dcd5918880630add6a482b1e549ae417 Mon Sep 17 00:00:00 2001 From: tannevaled Date: Fri, 28 Aug 2026 11:54:21 +0200 Subject: [PATCH] deps: Tab walks the panel, and a press puts the caret where it lands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit toolkit v0.277.0 lets the focus walk into a ScrollView and a FormField. Neither implemented focusableChildren, so a control inside a scrolling panel — which is where every control in this workbench lives — was invisible to it, and Tab reached nothing. Reaching them is only half of it: a child's Bounds do not move when the view scrolls, so the walk hands back the controls below the fold too, and the release scrolls the focused one into sight rather than leaving a cursor blinking where nobody can see it. The workbench's own routing stays. The toolkit walk now reaches these controls, but this still addresses the box it built and last saw pressed, because that is also what decides who an arrow key belongs to. AND A BEHAVIOUR CHANGE THIS HAD NOT NOTICED Bisecting the toolkit between v0.272.0 and v0.277.0 found the Marks panel test failing from v0.273.0, four releases before anything of ours. It is not a regression: v0.273.0 made a press put the caret WHERE IT LANDS instead of after the last letter, which is what a text box should do. These rows are pressed in the middle, and for a box that already holds a default that lands before the text — so typing "!" into the watermark gave "!DRAFT" rather than "DRAFT!". typeInto now sends the caret to the end first, which is what somebody adding to what is already there does. The test was encoding the old behaviour, not the intended one. A hazard looked at and NOT acted on: focusClick hit-tests with surface coordinates against Bounds that do not move when a view scrolls, so calling it directly on a scrolled view picks the wrong row — row 1 for a press five rows down. Through the real path it is masked: ScrollView.OnEvent translates the press and the child takes the caret itself, and a test that goes that way passes before the change as well as after. Nothing is shipped for it, because nothing demonstrates it. Co-Authored-By: Claude Opus 5 --- go.mod | 2 +- go.sum | 4 ++-- verbs_test.go | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9d69209..b254f76 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-pdfkit/reader v0.6.0 github.com/go-pdfkit/render v0.11.0 github.com/go-widgets/painter v0.11.0 - github.com/go-widgets/toolkit v0.272.0 + github.com/go-widgets/toolkit v0.277.0 github.com/go-widgets/webcanvas v0.1.0 ) diff --git a/go.sum b/go.sum index 0d785d5..0acf603 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/go-widgets/mvvm v0.5.0 h1:o5hh6HAxbApONcbZxmyV9q12pCAPGRd6L24aS3gaCbA github.com/go-widgets/mvvm v0.5.0/go.mod h1:Phdrd434RLxXW1D6dL1PPQH1tABwYLIN2X7jQVC4TbY= github.com/go-widgets/painter v0.11.0 h1:xsj4zTz8B43rOZnWrx7ZsaUBMgJyvgaE/Pq2FfcG2Sw= github.com/go-widgets/painter v0.11.0/go.mod h1:IPRLqdUJuJX8sfuHeYLZCzjoLvA0ApbOlyIAVmguJDQ= -github.com/go-widgets/toolkit v0.272.0 h1:TksXi4e3L8cuk37IfcdNgRzWFYqel+j0G7nZSLGJBTo= -github.com/go-widgets/toolkit v0.272.0/go.mod h1:eBfiAf9RI6uqmW6NoyFIBjNJgVmpjgVtVuJYS/8N5kI= +github.com/go-widgets/toolkit v0.277.0 h1:aMW3b9n+V6YY025sj327Ohs/coSHavKHz/7M5iu4+6Y= +github.com/go-widgets/toolkit v0.277.0/go.mod h1:Jgyk35WkerXSvQpQ4ZFYUywg/VLnox4s/7qCVyt4mS0= github.com/go-widgets/webcanvas v0.1.0 h1:fSGllghHlFZSC7CBb1oetj/PKR/S3ds/piDrpr0Kmg0= github.com/go-widgets/webcanvas v0.1.0/go.mod h1:UAoPu9dO6ZzcFFwQbVeW4Jm4X67XFKVJab9A6qWwsMM= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= diff --git a/verbs_test.go b/verbs_test.go index a85e29d..badd5a8 100644 --- a/verbs_test.go +++ b/verbs_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-pdfkit/extract" "github.com/go-pdfkit/ops" "github.com/go-pdfkit/reader" + "github.com/go-widgets/toolkit" ) // The heights of the rows of the groups this file drives. @@ -43,6 +44,12 @@ func content(t *testing.T, d *ops.Doc) []byte { } // typeInto puts the caret in the box on a row and types a word into it. +// +// The caret is sent to the end first. Since toolkit v0.273.0 a press puts the +// caret WHERE IT LANDS rather than after the last letter — which is what a text +// box should do — and these rows are pressed in the middle, which for a box +// that already holds a default lands before the text. Somebody adding to what +// is there goes to the end first, and so does this. func typeInto(t *testing.T, s *state, rows []int, n int, word string) { t.Helper() x, y := rowAt(t, s, rows, n, 1) @@ -50,6 +57,7 @@ func typeInto(t *testing.T, s *state, rows []int, n int, word string) { if !s.editing() { t.Fatalf("pressing row %d did not put the caret in a box", n) } + s.toCaret(toolkit.Event{Kind: toolkit.EventKeyDown, Code: "End"}) for _, c := range strings.Split(word, "") { if !s.handleChar(c) { t.Fatalf("row %d refused a character", n)