fyne-x icon indicating copy to clipboard operation
fyne-x copied to clipboard

CompletionEntry crash on fast input

Open itsjustdel opened this issue 2 years ago • 1 comments

Describe the bug:

Out of index error on fast input

To Reproduce:

Steps to reproduce the behaviour:

  1. Type four letters e.g "edin" quickly (difficult to get it to crash consistently) OR press the "simulate fast typing" button. This gives the same error as typing quickly

  2. See error

panic: runtime error: index out of range [3] with length 1

goroutine 18 [running, locked to thread]:
fyne.io/x/fyne/widget.newNavigableList.func3(0x7ff7e1196dd8?, {0x7ff7e1196150?, 0xc0000c48c0?})
        C:/Users/Del/go/pkg/mod/fyne.io/x/[email protected]/widget/completionentry.go:145 +0xf7
fyne.io/fyne/v2/widget.(*listLayout).setupListItem(0xc0000a81e0, 0xc00038ea10, 0x3)   
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/widget/list.go:411 +0x9b       
fyne.io/fyne/v2/widget.(*listLayout).updateList(0xc0000a81e0, 0x1)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/widget/list.go:456 +0x418      
fyne.io/fyne/v2/widget.(*listLayout).Layout(0x41600000000000f8?, {0x0?, 0xc0004295f8?, 0x7ff7e0ab5fb9?}, {0xecc1d0?, 0xc0?})
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/widget/list.go:369 +0x1e       
fyne.io/fyne/v2/internal/driver/common.updateLayout({0x7ff7e1195970?, 0xc00019a0c0?})
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:512 +0x70
fyne.io/fyne/v2/internal/driver/common.(*Canvas).EnsureMinSize.func1(0xc001002ac0)    
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:97 +0x235
fyne.io/fyne/v2/internal/driver/common.(*Canvas).walkTree.func2({0x7ff7e1195c70?, 0xc000e05300?}, {0xc000e05300?, 0xf542999ad?})
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:433 +0xae
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1195c70, 0xc000e05300}, 0x0, {0x7ff7e1196150, 0xc000d788c0}, {0xe1366c00?, 0x7ff7?}, {0x429838?, 0xc0?}, {0xe0aaaa6a?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:197 +0x370
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1196150, 0xc000d788c0}, 0x0, {0x7ff7e11963f0, 0xc000136e00}, {0xe0943be9?, 0x7ff7?}, {0x429888?, 0xd5000000?}, {0x0?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176    
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e11963f0, 0xc000136e00}, 0x0, {0x7ff7e1195970, 0xc00019a0c0}, {0xe1366c00?, 0x7ff7?}, {0x4299c8?, 0xc0?}, {0xe0aaaa6a?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176    
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1195970, 0xc00019a0c0}, 0x0, {0x7ff7e1195eb0, 0xc00038e3f0}, {0xe1366c00?, 0x7ff7?}, {0x429a90?, 0xc0?}, {0xe0aaaa6a?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176    
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1195eb0, 0xc00038e3f0}, 0x0, {0x7ff7e1196630, 0xc000198000}, {0xe1366c00?, 0x7ff7?}, {0x429b58?, 0xc0?}, {0xe0aaaa6a?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176    
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1196630, 0xc000198000}, 0x0, {0x7ff7e1196210, 0xc0000b2a00}, {0x429b80?, 0xc0?}, {0x429bc0?, 0xc0?}, {0xe0acb7b0?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.walkObjectTree.func1(...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:176    
fyne.io/fyne/v2/internal/driver.walkObjectTree({0x7ff7e1196210, 0xc0000b2a00}, 0x0, {0x0, 0x0}, {0x429c70?, 0xc0?}, {0x429c78?, 0x0?}, {0xe0c60ae6?, ...}, ...)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:190 +0x41d
fyne.io/fyne/v2/internal/driver.WalkVisibleObjectTree({0x7ff7e1196210?, 0xc0000b2a00?}, 0x7ff7e1194370?, 0xc00004e3c0?)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/util.go:134 +0x4c
fyne.io/fyne/v2/internal/driver/common.(*Canvas).walkTree(0x7ff7e0c3a2a4?, 0xc0000251a0, 0x0, 0xc000429df0)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:439 +0x165
fyne.io/fyne/v2/internal/driver/common.(*Canvas).WalkTrees(0xc0000ba000, 0x7ff7e0944467?, 0x0?)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:360 +0xd9
fyne.io/fyne/v2/internal/driver/common.(*Canvas).EnsureMinSize(0xc0000ba000)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/common/canvas.go:102 +0xf1
fyne.io/fyne/v2/internal/driver/glfw.(*gLDriver).repaintWindow.func1()
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/glfw/loop.go:166 +0x35
fyne.io/fyne/v2/internal/driver/glfw.(*window).RunWithContext(0xc0000b4000, 0xc000429ea0)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/glfw/window.go:1329 +0x4f
fyne.io/fyne/v2/internal/driver/glfw.(*gLDriver).repaintWindow(0xc000429f90?, 0xc000429f18?)
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/glfw/loop.go:165 +0x4a
fyne.io/fyne/v2/internal/driver/glfw.(*gLDriver).startDrawThread.func1()
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/glfw/loop.go:228 +0x33a
created by fyne.io/fyne/v2/internal/driver/glfw.(*gLDriver).startDrawThread
        C:/Users/Del/go/pkg/mod/fyne.io/fyne/[email protected]/internal/driver/glfw/loop.go:192 +0xca
exit status 2```

### Screenshot
![auto](https://user-images.githubusercontent.com/45520351/170705661-8eea228e-db06-4d22-ad56-cfc604ccb26d.png)

### Example code:
```package main

import (
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	xWidget "fyne.io/x/fyne/widget"
	"github.com/tidwall/cities"
)

func main() {

	a := app.New()
	w := a.NewWindow("Entry Completion")

	entry := xWidget.NewCompletionEntry([]string{})

	// When the use typed text, complete the list.
	cardTexts := []string{}

	entry.OnChanged = func(s string) {

		results := []cities.City{}

		for _, value := range cities.Cities {

			if len(value.City) < len(s) {
				continue
			}

			if strings.EqualFold(s, value.City[:len(s)]) {
				results = append(results, value)
			}
		}

		if len(results) == 0 {
			entry.HideCompletion()
			return
		}

		cardTexts = []string{}
		for _, r := range results {
			s := r.City
			cardTexts = append(cardTexts, s)
		}

		entry.SetOptions(cardTexts)
		entry.ShowCompletion()
	}

	button := widget.NewButton("Simulate fast typing", func() {

		for {
			entry.SetText("")
			entry.SetText(entry.Text + "edin")
		}
	})

	w.SetContent(container.NewVBox(button, entry))

	w.Resize(fyne.NewSize(700, 500))
	w.ShowAndRun()

}

Device (please complete the following information):

  • OS: Windows
  • Version: 10
  • Go version: go1.18.1
  • Fyne version: v2.1.4

itsjustdel avatar May 27 '22 13:05 itsjustdel

Hello, I've faced the same issue. From time to time I have a crash during typing someting to entry, while list of options is modified basis on entered text.

I see that crash is there:

/widget/completionentry.go:165 

UpdateItem: func(i widget.ListItemID, o fyne.CanvasObject) {
    if fn := n.customUpdate; fn != nil {
        fn(i, o)
        return
    }
    o.(*widget.Label).SetText(n.items[i])
}

While UpdateItem is executed, n.items slice is shorter than index i indicates, which lead to crash.

Workaround is to use own customUpdate function like:

entry := xwidget.NewCompletionEntry([]string{})

entry.CustomUpdate = func(i widget.ListItemID, o fyne.CanvasObject) {
    options := entry.Options

    if i >= len(options) {
        return
    }

    o.(*widget.Label).SetText(options[i])
} 

Or wait a little bit between setting an options for entry and calling ShowCompletion()

In @itsjustdel example it will looks like:

entry.SetOptions(cardTexts)
time.Sleep(10 * time.Millisecond)
entry.ShowCompletion()

which I don't like personally.

Nevertheless I was not able to reproduce this issue using unit tests for this widget.

  • OS: Windows
  • Version: 10
  • Go version: go1.20
  • Fyne version: v2.3.1
  • Fyne-x version: v0.0.0-20230128220048-43a1c4cd1ed8

sharki13 avatar Feb 16 '23 21:02 sharki13