diff --git a/internal/driver/glfw/canvas.go b/internal/driver/glfw/canvas.go index 265763cc3f..3db030c6f7 100644 --- a/internal/driver/glfw/canvas.go +++ b/internal/driver/glfw/canvas.go @@ -84,12 +84,16 @@ func (c *glCanvas) Focus(obj fyne.Focusable) { c.RUnlock() for _, mgr := range focusMgrs { + if mgr == nil { + continue + } if focusMgr != mgr { if mgr.Focus(obj) { return } } } + fyne.LogError("Failed to focus object which is not part of the canvas’ content, menu or overlays.", nil) } @@ -452,7 +456,14 @@ func (c *glCanvas) paint(size fyne.Size) { func (c *glCanvas) setContent(content fyne.CanvasObject) { c.content = content c.contentTree = &renderCacheTree{root: &renderCacheNode{obj: c.content}} + var focused fyne.Focusable + if c.contentFocusMgr != nil { + focused = c.contentFocusMgr.Focused() // keep old focus if possible + } c.contentFocusMgr = app.NewFocusManager(c.content) + if focused != nil { + c.contentFocusMgr.Focus(focused) + } } func (c *glCanvas) setDirty(dirty bool) { diff --git a/internal/driver/glfw/canvas_test.go b/internal/driver/glfw/canvas_test.go index f5f6ccfe0e..fae107ec97 100644 --- a/internal/driver/glfw/canvas_test.go +++ b/internal/driver/glfw/canvas_test.go @@ -204,6 +204,27 @@ func TestGlCanvas_Focus(t *testing.T) { assert.True(t, o2e.focused) } +func TestGlCanvas_Focus_BeforeVisible(t *testing.T) { + w := createWindow("Test") + w.SetPadded(false) + e := widget.NewEntry() + c := w.Canvas().(*glCanvas) + c.Focus(e) // this crashed in the past +} + +func TestGlCanvas_Focus_SetContent(t *testing.T) { + w := createWindow("Test") + w.SetPadded(false) + e := widget.NewEntry() + w.SetContent(container.NewHBox(e)) + c := w.Canvas().(*glCanvas) + c.Focus(e) + assert.Equal(t, e, c.Focused()) + + w.SetContent(container.NewVBox(e)) + assert.Equal(t, e, c.Focused()) +} + func TestGlCanvas_FocusHandlingWhenAddingAndRemovingOverlays(t *testing.T) { w := createWindow("Test") w.SetPadded(false)