Repository: fyne-io/fyne
File: internal/driver/glfw/loop.go (Go)

Code before:

	funcQueue <- funcData{f: f, done: done}

	<-done
}

// force a function f to run on the draw thread
func runOnDraw(w *window, f func()) {
	if drawOnMainThread {
		runOnMain(func() { w.RunWithContext(f) })
		return
	}
	done := common.DonePool.Get().(chan struct{})
	defer common.DonePool.Put(done)

	drawFuncQueue <- drawData{f: f, win: w, done: done}
	<-done
}

// Preallocate to avoid allocations on every drawSingleFrame.
// Note that the capacity of this slice can only grow,
// but its length will never be longer than the total number of
// window canvases that are dirty on a single frame.
// So its memory impact should be negligible and does not
// need periodic shrinking.
var refreshingCanvases = make([]fyne.Canvas, 0)

func (d *gLDriver) drawSingleFrame() {
	for _, win := range d.windowList() {
		w := win.(*window)
		w.viewLock.RLock()
		canvas := w.canvas
		closing := w.closing
		visible := w.visible
		w.viewLock.RUnlock()

		// CheckDirtyAndClear must be checked after visibility,
		// because when a window becomes visible, it could be
		// showing old content without a dirty flag set to true.
		// Do the clear if and only if the window is visible.
		if closing || !visible || !canvas.CheckDirtyAndClear() {
			continue
		}

		d.repaintWindow(w)
		refreshingCanvases = append(refreshingCanvases, canvas)
	}
	cache.CleanCanvases(refreshingCanvases)

	// cleanup refreshingCanvases slice
	for i := 0; i < len(refreshingCanvases); i++ {

Review comment (bug):
You don't have make it into zero size. Doing so does an unnecessary call to the runtime per https://stackoverflow.com/a/29164565.  Just do this instead:
```suggestion
var refreshingCanvases []fyne.Canvas
```


Code after:

	funcQueue <- funcData{f: f, done: done}

	<-done
}

// force a function f to run on the draw thread
func runOnDraw(w *window, f func()) {
	if drawOnMainThread {
		runOnMain(func() { w.RunWithContext(f) })
		return
	}
	done := common.DonePool.Get().(chan struct{})
	defer common.DonePool.Put(done)

	drawFuncQueue <- drawData{f: f, win: w, done: done}
	<-done
}

// Preallocate to avoid allocations on every drawSingleFrame.
// Note that the capacity of this slice can only grow,
// but its length will never be longer than the total number of
// window canvases that are dirty on a single frame.
// So its memory impact should be negligible and does not
// need periodic shrinking.
var refreshingCanvases []fyne.Canvas

func (d *gLDriver) drawSingleFrame() {
	for _, win := range d.windowList() {
		w := win.(*window)
		w.viewLock.RLock()
		canvas := w.canvas
		closing := w.closing
		visible := w.visible
		w.viewLock.RUnlock()

		// CheckDirtyAndClear must be checked after visibility,
		// because when a window becomes visible, it could be
		// showing old content without a dirty flag set to true.
		// Do the clear if and only if the window is visible.
		if closing || !visible || !canvas.CheckDirtyAndClear() {
			continue
		}

		d.repaintWindow(w)
		refreshingCanvases = append(refreshingCanvases, canvas)
	}
	cache.CleanCanvases(refreshingCanvases)

	// cleanup refreshingCanvases slice
	for i := 0; i < len(refreshingCanvases); i++ {