Skip to content

Commit

Permalink
Fix issue with Focus call crashing
Browse files Browse the repository at this point in the history
Fixes #1893
  • Loading branch information
andydotxyz committed Feb 18, 2021
1 parent 284258a commit b2e10e9
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
12 changes: 12 additions & 0 deletions internal/app/focus_manager.go
Expand Up @@ -59,6 +59,18 @@ func (f *FocusManager) Focus(obj fyne.Focusable) bool {
return true
}

// FocusBeforeAdded allows an object to be focused before it is added to the object tree.
// This is typically used before a canvas is visible and should be used with care.
func (f *FocusManager) FocusBeforeAdded(obj fyne.Focusable) {
f.RLock()
defer f.RUnlock()
if dis, ok := obj.(fyne.Disableable); ok && dis.Disabled() {
return
}

f.focus(obj)
}

// Focused returns the currently focused object or nil if none.
func (f *FocusManager) Focused() fyne.Focusable {
f.RLock()
Expand Down
13 changes: 12 additions & 1 deletion internal/driver/glfw/canvas.go
Expand Up @@ -84,13 +84,17 @@ 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)

c.contentFocusMgr.FocusBeforeAdded(obj) // not found yet assume we are preparing the UI
}

func (c *glCanvas) Focused() fyne.Focusable {
Expand Down Expand Up @@ -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) {
Expand Down
11 changes: 11 additions & 0 deletions internal/driver/glfw/canvas_test.go
Expand Up @@ -204,6 +204,17 @@ 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

w.SetContent(e)
assert.Equal(t, e, c.Focused(), "Item set to focus before SetContent was not focused after")
}

func TestGlCanvas_FocusHandlingWhenAddingAndRemovingOverlays(t *testing.T) {
w := createWindow("Test")
w.SetPadded(false)
Expand Down

0 comments on commit b2e10e9

Please sign in to comment.