Give the find bar's input focus and the keyboard when it opens

Tapping the search icon set FocusedElementID to find_bar (so the editor
stopped its IME sync), but the main-owned widget.Editor only grabs key
focus on its own click — the icon tap never touches it, so neither focus
nor the soft keyboard moved to the search input.

Main now watches the frame's FocusedElementID and, on the transition
into find_bar, issues key.FocusCmd{Tag: &findEditor} (once per open).
The widget's FocusEvent handler raises the soft keyboard on focus gain
(gioui.org/widget/editor.go), so the keyboard follows automatically;
w.Invalidate guarantees the frame in which the widget sees the FocusEvent.
Close needs no inverse action: the editor's TextField re-issues its own
FocusCmd because the renderer clears the focus dedup on frames where no
logic field is focused.
This commit is contained in:
Greg Pomerantz 2026-08-20 12:24:01 -04:00
parent 587c1c5aad
commit cfaf4927ac

View File

@ -128,6 +128,10 @@ func run(w *app.Window) error {
// the set changes — the rects move every frame while a selection is
// visible/scrolling, but identical repeats are skipped.
var lastExcl [][4]int
// findBarFocused tracks whether the previous frame focused the find bar's
// main-owned input, so main hands key focus to it exactly once per open
// (see the focus handoff below).
var findBarFocused bool
for {
switch e := w.Event().(type) {
@ -233,6 +237,19 @@ func run(w *app.Window) error {
// Gather key events
focusedID := frame.FocusedElementID
// Hand key focus to the find bar's main-owned input the moment the
// find bar opens: the search-icon tap never touches the widget, and
// widget.Editor only grabs key focus on its own click (gioui.org/
// widget/editor.go). The widget's FocusEvent handler raises the soft
// keyboard on focus gain, so the keyboard follows automatically. On
// the inverse transition the editor's TextField re-issues its own
// key.FocusCmd (the renderer clears the focus dedup on frames where
// no logic field is focused), so nothing is needed on close.
if focusedID == "find_bar" && !findBarFocused {
gtx.Execute(key.FocusCmd{Tag: &findEditor})
w.Invalidate() // next frame: the widget sees the FocusEvent
}
findBarFocused = focusedID == "find_bar"
if focusedID == "" {
// No focused input: drop any stale shift state (a release event
// for a key held across focus loss may never arrive).