Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a fyne.Do method for developers #5392

Merged
merged 4 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (a *fyneApp) NewWindow(title string) fyne.Window {
}

func (a *fyneApp) Run() {
go a.lifecycle.RunEventQueue(a.driver.CallFromGoroutine)
go a.lifecycle.RunEventQueue(a.driver.DoFromGoroutine)
a.driver.Run()
}

Expand Down
2 changes: 1 addition & 1 deletion app/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (p *preferences) resetSavedRecently() {
time.Sleep(time.Millisecond * 100) // writes are not always atomic. 10ms worked, 100 is safer.

// For test reasons we need to use current app not what we were initialised with as they can differ
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
p.prefLock.Lock()
p.savedRecently = false
changedDuringSaving := p.changedDuringSaving
Expand Down
2 changes: 1 addition & 1 deletion app/preferences_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ func (p *preferences) watch() {
return
}

fyne.CurrentApp().Driver().CallFromGoroutine(p.load)
fyne.Do(p.load)
})
}
2 changes: 1 addition & 1 deletion cmd/fyne_demo/tutorials/advanced.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func advancedScreen(win fyne.Window) fyne.CanvasObject {

go func(canvas fyne.Canvas) {
for range time.NewTicker(time.Second).C {
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
scale.SetText(scaleToString(canvas))
tex.SetText(textureScaleToString(canvas))
})
Expand Down
2 changes: 1 addition & 1 deletion cmd/fyne_demo/tutorials/canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func canvasScreen(_ fyne.Window) fyne.CanvasObject {
gradient := canvas.NewHorizontalGradient(color.NRGBA{0x80, 0, 0, 0xff}, color.NRGBA{0, 0x80, 0, 0xff})
go func() {
for range time.NewTicker(time.Second).C {
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
gradient.Angle += 45
if gradient.Angle >= 360 {
gradient.Angle -= 360
Expand Down
2 changes: 1 addition & 1 deletion cmd/fyne_demo/tutorials/welcome.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func welcomeScreen(_ fyne.Window) fyne.CanvasObject {
fyne.CurrentApp().Settings().AddChangeListener(listen)
go func() {
for range listen {
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
bgColor = withAlpha(theme.Color(theme.ColorNameBackground), 0xe0)
bg.FillColor = bgColor
bg.Refresh()
Expand Down
4 changes: 2 additions & 2 deletions cmd/fyne_demo/tutorials/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func makeActivityTab(win fyne.Window) fyne.CanvasObject {
a2.Show()

time.AfterFunc(10*time.Second, func() {
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
a1.Stop()
a1.Hide()
a2.Stop()
Expand Down Expand Up @@ -90,7 +90,7 @@ func makeActivityTab(win fyne.Window) fyne.CanvasObject {
d.Show()

time.AfterFunc(5*time.Second, func() {
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.Do(func() {
a3.Stop()
d.Hide()
})
Expand Down
2 changes: 1 addition & 1 deletion cmd/fyne_demo/tutorials/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func windowScreen(_ fyne.Window) fyne.CanvasObject {
w.Show()

time.AfterFunc(3*time.Second, func() {
fyne.CurrentApp().Driver().CallFromGoroutine(w.Close)
fyne.Do(w.Close)
})
}))
}
Expand Down
2 changes: 1 addition & 1 deletion data/binding/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ func queueItem(f func()) {
return
}

fyne.CurrentApp().Driver().CallFromGoroutine(f)
fyne.Do(f)
}
6 changes: 4 additions & 2 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ type Driver interface {
// Since: 2.5
SetDisableScreenBlanking(bool)

// CallFromGoroutine provides a way to queue a function that is running on a goroutine back to the main thread.
// DoFromGoroutine provides a way to queue a function that is running on a goroutine back to
// the central thread for Fyne updates.
// This is required when background tasks want to execute code safely in the graphical context.
//
// Since: 2.6
CallFromGoroutine(func())
DoFromGoroutine(func())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to un-export this one for public use to avoid confusion, so we just have fyne.Do? Or at least have the documentation here make clear that it is entirely equivalent to calling fyne.Do and fyne.Do should generally be preferred (for brevity and for standardization)?

}
2 changes: 1 addition & 1 deletion internal/driver/glfw/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func toOSIcon(icon []byte) ([]byte, error) {
return buf.Bytes(), nil
}

func (d *gLDriver) CallFromGoroutine(f func()) {
func (d *gLDriver) DoFromGoroutine(f func()) {
runOnMain(f)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/driver/mobile/canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ func (c *canvas) waitForDoubleTap(co fyne.CanvasObject, ev *fyne.PointEvent, tap
defer cancel()

<-ctx.Done()
fyne.CurrentApp().Driver().CallFromGoroutine(func() {
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
c.touchCancelLock.Lock()
touchCount := c.touchTapCount
touchLast := c.touchLastTapped
Expand Down
8 changes: 4 additions & 4 deletions internal/driver/mobile/canvas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func Test_canvas_Focusable(t *testing.T) {
content.Resize(fyne.NewSize(25, 25))

pos := fyne.NewPos(10, 10)
d.CallFromGoroutine(func() {
d.DoFromGoroutine(func() {
c.tapDown(pos, 0)
c.tapUp(pos, 0, func(wid fyne.Tappable, ev *fyne.PointEvent) {
wid.Tapped(ev)
Expand All @@ -149,7 +149,7 @@ func Test_canvas_Focusable(t *testing.T) {
assert.Equal(t, 0, content.unfocusedTimes)
})

d.CallFromGoroutine(func() {
d.DoFromGoroutine(func() {
c.tapDown(pos, 1)
c.tapUp(pos, 1, func(wid fyne.Tappable, ev *fyne.PointEvent) {
wid.Tapped(ev)
Expand All @@ -160,7 +160,7 @@ func Test_canvas_Focusable(t *testing.T) {
assert.Equal(t, 0, content.unfocusedTimes)
})

d.CallFromGoroutine(func() {
d.DoFromGoroutine(func() {
c.Focus(content)
assert.Equal(t, 1, content.focusedTimes)
assert.Equal(t, 0, content.unfocusedTimes)
Expand Down Expand Up @@ -530,7 +530,7 @@ func waitAndCheck(msWait time.Duration, fn func()) {
defer common.DonePool.Put(waitForCheck)

time.Sleep(msWait * time.Millisecond)
d.CallFromGoroutine(func() {
d.DoFromGoroutine(func() {
fn()

waitForCheck <- struct{}{}
Expand Down
8 changes: 3 additions & 5 deletions internal/driver/mobile/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func init() {
runtime.LockOSThread()
}

func (d *driver) CallFromGoroutine(fn func()) {
func (d *driver) DoFromGoroutine(fn func()) {
done := common.DonePool.Get()
defer common.DonePool.Put(done)

Expand Down Expand Up @@ -433,15 +433,13 @@ func (d *driver) tapUpCanvas(w *window, x, y float32, tapID touch.Sequence) {
ev.Dragged.DY *= tapMoveDecay
}

d.CallFromGoroutine(func() {
d.DoFromGoroutine(func() {
wid.Dragged(ev)
})
time.Sleep(time.Millisecond * 16)
}

d.CallFromGoroutine(func() {
wid.DragEnd()
})
d.DoFromGoroutine(wid.DragEnd)
}()
})
}
Expand Down
2 changes: 1 addition & 1 deletion test/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func (s *testSettings) apply() {
listener <- s
}

s.app.driver.CallFromGoroutine(func() {
s.app.driver.DoFromGoroutine(func() {
s.app.propertyLock.Lock()
painter.ClearFontCache()
cache.ResetThemeCaches()
Expand Down
2 changes: 1 addition & 1 deletion test/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewDriverWithPainter(painter SoftwarePainter) fyne.Driver {
return &driver{painter: painter}
}

func (d *driver) CallFromGoroutine(f func()) {
func (d *driver) DoFromGoroutine(f func()) {
f() // Tests all run on a single (but potentially different per-test) thread
}

Expand Down
10 changes: 10 additions & 0 deletions thread.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fyne

// Do is used to execute a specified function in the main Fyne runtime context.
// This is required when a background processes wishes to adjust graphical elements of a running app.
dweymouth marked this conversation as resolved.
Show resolved Hide resolved
// Developers should use this only from within goroutines they have created.
//
// Since: 2.6
func Do(fn func()) {
CurrentApp().Driver().DoFromGoroutine(fn)
}
Loading