Bevy version
0.13
What went wrong
JavaScript is an interpreted language, and the browser will essentially suspend code execution completely if the tab is hidden. Bevy's systems are tied to requestAnimationFrame, which is also completely paused when the user is tabbed away from the window.
In other words: On wasm, the main thread gets suspended when it is hidden (e.g. when the user switches tabs). This means that the app.update() function will not be called, because bevy's scheduler only runs app.update() when the browser's requestAnimationFrame is called (and that happens only when the tab is visible).
What problem does this cause?
- No systems will execute whilst the tab is inactive. This means networking crates will disconnect easily (no communications being sent while alt-tabbed).
- Networking crates that don't disconnect may experience buffer overflows for bounded protocols, as they will process hundreds of missed packets all at once. This could result in dropped packets.
There's a very long discussion on how this problem affects lightyear available here. We eventually come to a solution, which I'll propose below.
The part about winit::TabLeft
So yeah, there is technically events like Event::Suspended in winit that are supposed to fire when the tab gets left. However, as aforementioned, no code executes when the tab is hidden. As a result, this event is handled only when you return to the tab!
< user leaves tab >
... 30 seconds
< user goes back to the tab >
--> new event: Event::Suspended
--> new event: Event::Resumed
And what use is that? It's delivering no value currently. I'd call this a bug.
The solution
A solution, credited to @Nul-led , is to add a very small plugin (~10 lines of code) to spawn a web worker which sends a message every 1 second (configurable time). A callback is added to the web browser's DOM events to execute the main schedule exactly 1 time.
The code can be seen here: https://github.com/cBournhonesque/lightyear/pull/371/files#diff-5ec95d0ed493b4b63bba9ae693c990e6e1612d2fbe6309df678bf21fb75fbc1b
What I want
Selfishly, I want to see this in bevy. It's a very small amount of code but could be massively beneficial to many crates who want to keep a continuous run in the background when the tab is inactive.
Specifically, I think this should be a
pub struct WebExecutionPlugin {
callback_ms: f32 // default = 250.0 ms
}
that can be added to any application.
Furthermore, it would be nice to have a
#[derive(States)]
pub enum WindowFocusState {
Inactive,
Active,
}
that changes, depending on whether the window or tab is visible.
Bevy version
0.13
What went wrong
JavaScript is an interpreted language, and the browser will essentially suspend code execution completely if the tab is hidden. Bevy's systems are tied to
requestAnimationFrame, which is also completely paused when the user is tabbed away from the window.In other words: On wasm, the main thread gets suspended when it is hidden (e.g. when the user switches tabs). This means that the app.update() function will not be called, because bevy's scheduler only runs app.update() when the browser's
requestAnimationFrameis called (and that happens only when the tab is visible).What problem does this cause?
There's a very long discussion on how this problem affects lightyear available here. We eventually come to a solution, which I'll propose below.
The part about
winit::TabLeftSo yeah, there is technically events like
Event::Suspendedin winit that are supposed to fire when the tab gets left. However, as aforementioned, no code executes when the tab is hidden. As a result, this event is handled only when you return to the tab!< user leaves tab >
... 30 seconds
< user goes back to the tab >
--> new event:
Event::Suspended--> new event:
Event::ResumedAnd what use is that? It's delivering no value currently. I'd call this a bug.
The solution
A solution, credited to @Nul-led , is to add a very small plugin (~10 lines of code) to spawn a web worker which sends a message every 1 second (configurable time). A callback is added to the web browser's DOM events to execute the main schedule exactly 1 time.
The code can be seen here: https://github.com/cBournhonesque/lightyear/pull/371/files#diff-5ec95d0ed493b4b63bba9ae693c990e6e1612d2fbe6309df678bf21fb75fbc1b
What I want
Selfishly, I want to see this in bevy. It's a very small amount of code but could be massively beneficial to many crates who want to keep a continuous run in the background when the tab is inactive.
Specifically, I think this should be a
that can be added to any application.
Furthermore, it would be nice to have a
that changes, depending on whether the window or tab is visible.