diff --git a/internal/ui/ui_mobile.go b/internal/ui/ui_mobile.go index 998c1cfa0..2ff3dcb25 100644 --- a/internal/ui/ui_mobile.go +++ b/internal/ui/ui_mobile.go @@ -22,6 +22,7 @@ import ( "runtime/debug" "sync" "sync/atomic" + "time" "unicode" "golang.org/x/mobile/app" @@ -54,6 +55,7 @@ var ( func init() { theUI.userInterfaceImpl = userInterfaceImpl{ foreground: 1, + runnableOnUnfocused: 0, // This is 0 for backward compatibility during v2 (#2576). graphicsDriverInitCh: make(chan struct{}), errCh: make(chan error), @@ -73,7 +75,8 @@ func (u *userInterfaceImpl) Update() error { default: } - if !u.IsFocused() { + if !u.IsFocused() && !u.IsRunnableOnUnfocused() { + time.Sleep(time.Second / 60) return nil } @@ -101,8 +104,9 @@ type userInterfaceImpl struct { outsideWidth float64 outsideHeight float64 - foreground int32 - errCh chan error + foreground int32 + runnableOnUnfocused int32 + errCh chan error // Used for gomobile-build gbuildWidthPx int @@ -232,9 +236,11 @@ func (u *userInterfaceImpl) SetForeground(foreground bool) error { if foreground { return hooks.ResumeAudio() - } else { + } + if !u.IsRunnableOnUnfocused() { return hooks.SuspendAudio() } + return nil } func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { @@ -395,11 +401,15 @@ func (u *userInterfaceImpl) IsFocused() bool { } func (u *userInterfaceImpl) IsRunnableOnUnfocused() bool { - return false + return atomic.LoadInt32(&u.runnableOnUnfocused) != 0 } func (u *userInterfaceImpl) SetRunnableOnUnfocused(runnableOnUnfocused bool) { - // Do nothing + var v int32 + if runnableOnUnfocused { + v = 1 + } + atomic.StoreInt32(&u.runnableOnUnfocused, v) } func (u *userInterfaceImpl) SetFPSMode(mode FPSModeType) { diff --git a/run.go b/run.go index 98bf929fd..2a0dd7cf0 100644 --- a/run.go +++ b/run.go @@ -428,13 +428,13 @@ func IsRunnableOnUnfocused() bool { // SetRunnableOnUnfocused sets the state if the game runs even in background. // // If the given value is true, the game runs even in background e.g. when losing focus. -// The initial state is true. +// The initial state is true on desktops, and false on mobiles. +// For mobiles, in addition to SetRunnableOnUnfocused, you might require some permission settings +// not to pause audio when the application goes to background. // // Known issue: On browsers, even if the state is on, the game doesn't run in background tabs. // This is because browsers throttles background tabs not to often update. // -// SetRunnableOnUnfocused does nothing on mobiles so far. -// // SetRunnableOnUnfocused is concurrent-safe. func SetRunnableOnUnfocused(runnableOnUnfocused bool) { ui.Get().SetRunnableOnUnfocused(runnableOnUnfocused)