mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 10:42:42 +01:00
uidriver/js: Bug fix: Watch the state regularly instead of events
visibilitystate is sometimes not called and in this case the app does not come back. This fix creates another goroutine to watch the state, and remove event handlers. Fixes #961
This commit is contained in:
parent
016a9a6923
commit
e7611139c3
@ -22,13 +22,12 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
||||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
var canvas js.Value
|
|
||||||
|
|
||||||
type UserInterface struct {
|
type UserInterface struct {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
@ -37,8 +36,6 @@ type UserInterface struct {
|
|||||||
vsync bool
|
vsync bool
|
||||||
|
|
||||||
sizeChanged bool
|
sizeChanged bool
|
||||||
windowFocus bool
|
|
||||||
pageVisible bool
|
|
||||||
contextLost bool
|
contextLost bool
|
||||||
|
|
||||||
lastActualScale float64
|
lastActualScale float64
|
||||||
@ -53,8 +50,6 @@ type UserInterface struct {
|
|||||||
|
|
||||||
var theUI = &UserInterface{
|
var theUI = &UserInterface{
|
||||||
sizeChanged: true,
|
sizeChanged: true,
|
||||||
windowFocus: true,
|
|
||||||
pageVisible: true,
|
|
||||||
vsync: true,
|
vsync: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +64,7 @@ func Get() *UserInterface {
|
|||||||
var (
|
var (
|
||||||
window = js.Global().Get("window")
|
window = js.Global().Get("window")
|
||||||
document = js.Global().Get("document")
|
document = js.Global().Get("document")
|
||||||
|
canvas js.Value
|
||||||
requestAnimationFrame = window.Get("requestAnimationFrame")
|
requestAnimationFrame = window.Get("requestAnimationFrame")
|
||||||
setTimeout = window.Get("setTimeout")
|
setTimeout = window.Get("setTimeout")
|
||||||
)
|
)
|
||||||
@ -189,7 +185,17 @@ func (u *UserInterface) updateSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) suspended() bool {
|
func (u *UserInterface) suspended() bool {
|
||||||
return !u.runnableInBackground && (!u.windowFocus || !u.pageVisible)
|
if u.runnableInBackground {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !document.Call("hasFocus").Bool() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if document.Get("hidden").Bool() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) update() error {
|
func (u *UserInterface) update() error {
|
||||||
@ -210,7 +216,7 @@ func (u *UserInterface) update() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) loop(context driver.UIContext) <-chan error {
|
func (u *UserInterface) loop(context driver.UIContext) <-chan error {
|
||||||
u.init(context)
|
u.context = context
|
||||||
|
|
||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
var cf js.Func
|
var cf js.Func
|
||||||
@ -238,38 +244,23 @@ func (u *UserInterface) loop(context driver.UIContext) <-chan error {
|
|||||||
go func() {
|
go func() {
|
||||||
f(js.Value{}, nil)
|
f(js.Value{}, nil)
|
||||||
}()
|
}()
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) init(context driver.UIContext) {
|
// Run another loop to watch suspended() as the above update function is never called when the tab is hidden.
|
||||||
u.context = context
|
// To check the document's visiblity, visibilitychange event should usually be used. However, this event is
|
||||||
window.Call("addEventListener", "focus", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
// not reliable and sometimes it is not fired (#961). Then, watch the state regularly instead.
|
||||||
u.windowFocus = true
|
go func() {
|
||||||
if u.suspended() {
|
t := time.NewTicker(100 * time.Millisecond)
|
||||||
u.context.SuspendAudio()
|
defer t.Stop()
|
||||||
} else {
|
for range t.C {
|
||||||
u.context.ResumeAudio()
|
if u.suspended() {
|
||||||
|
u.context.SuspendAudio()
|
||||||
|
} else {
|
||||||
|
u.context.ResumeAudio()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
}()
|
||||||
}))
|
|
||||||
window.Call("addEventListener", "blur", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
return ch
|
||||||
u.windowFocus = false
|
|
||||||
if u.suspended() {
|
|
||||||
u.context.SuspendAudio()
|
|
||||||
} else {
|
|
||||||
u.context.ResumeAudio()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}))
|
|
||||||
document.Call("addEventListener", "visibilitychange", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
|
||||||
u.pageVisible = !document.Get("hidden").Bool()
|
|
||||||
if u.suspended() {
|
|
||||||
u.context.SuspendAudio()
|
|
||||||
} else {
|
|
||||||
u.context.ResumeAudio()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
Loading…
Reference in New Issue
Block a user