mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
Fix winit control flow when re-focusing game (#12239)
# Objective Fixes #12126 Notably this does not appear to fix the console error spam that appears to be coming from winit, only the performance bug that occurs when tabbing out and back into the game. ## Solution The winit event loop starts out as `ControlFlow::Wait` by default. When switching to `UpdateMode::Reactive` or `UpdateMode::ReactiveLowPower`, we repeatedly update this to `ControlFlow::WaitUntil(next)`. When switching back to `UpdateMode::Continuous`, the event loop is erroneously stuck at the latest `ControlFlow::WaitUntil(next)` that was issued. I also changed how we handle `Event::NewEvents` since the `StartCause` already tells us enough information to make that decision. This came about my debugging and I left it in as an improvement.
This commit is contained in:
parent
ccb9d0500f
commit
d6a7319106
1 changed files with 11 additions and 12 deletions
|
@ -14,7 +14,7 @@ mod winit_windows;
|
||||||
|
|
||||||
use approx::relative_eq;
|
use approx::relative_eq;
|
||||||
use bevy_a11y::AccessibilityRequested;
|
use bevy_a11y::AccessibilityRequested;
|
||||||
use bevy_utils::{Duration, Instant};
|
use bevy_utils::Instant;
|
||||||
use system::{changed_windows, create_windows, despawn_windows, CachedWindow};
|
use system::{changed_windows, create_windows, despawn_windows, CachedWindow};
|
||||||
use winit::dpi::{LogicalSize, PhysicalSize};
|
use winit::dpi::{LogicalSize, PhysicalSize};
|
||||||
pub use winit_config::*;
|
pub use winit_config::*;
|
||||||
|
@ -46,6 +46,7 @@ use bevy_window::{PrimaryWindow, RawHandleWrapper};
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
pub use winit::platform::android::activity as android_activity;
|
pub use winit::platform::android::activity as android_activity;
|
||||||
|
|
||||||
|
use winit::event::StartCause;
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{self, DeviceEvent, Event, WindowEvent},
|
event::{self, DeviceEvent, Event, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget},
|
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget},
|
||||||
|
@ -184,8 +185,6 @@ struct WinitAppRunnerState {
|
||||||
wait_elapsed: bool,
|
wait_elapsed: bool,
|
||||||
/// The time the last update started.
|
/// The time the last update started.
|
||||||
last_update: Instant,
|
last_update: Instant,
|
||||||
/// The time the next update is scheduled to start.
|
|
||||||
scheduled_update: Option<Instant>,
|
|
||||||
/// Number of "forced" updates to trigger on application start
|
/// Number of "forced" updates to trigger on application start
|
||||||
startup_forced_updates: u32,
|
startup_forced_updates: u32,
|
||||||
}
|
}
|
||||||
|
@ -226,7 +225,6 @@ impl Default for WinitAppRunnerState {
|
||||||
redraw_requested: false,
|
redraw_requested: false,
|
||||||
wait_elapsed: false,
|
wait_elapsed: false,
|
||||||
last_update: Instant::now(),
|
last_update: Instant::now(),
|
||||||
scheduled_update: None,
|
|
||||||
// 3 seems to be enough, 5 is a safe margin
|
// 3 seems to be enough, 5 is a safe margin
|
||||||
startup_forced_updates: 5,
|
startup_forced_updates: 5,
|
||||||
}
|
}
|
||||||
|
@ -411,12 +409,14 @@ fn handle_winit_event(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::NewEvents(_) => {
|
Event::NewEvents(cause) => {
|
||||||
if let Some(t) = runner_state.scheduled_update {
|
runner_state.wait_elapsed = match cause {
|
||||||
let now = Instant::now();
|
StartCause::WaitCancelled {
|
||||||
let remaining = t.checked_duration_since(now).unwrap_or(Duration::ZERO);
|
requested_resume: Some(resume),
|
||||||
runner_state.wait_elapsed = remaining.is_zero();
|
..
|
||||||
}
|
} => resume >= Instant::now(),
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Event::WindowEvent {
|
Event::WindowEvent {
|
||||||
event, window_id, ..
|
event, window_id, ..
|
||||||
|
@ -762,6 +762,7 @@ fn run_app_update_if_should(
|
||||||
match config.update_mode(focused) {
|
match config.update_mode(focused) {
|
||||||
UpdateMode::Continuous => {
|
UpdateMode::Continuous => {
|
||||||
runner_state.redraw_requested = true;
|
runner_state.redraw_requested = true;
|
||||||
|
event_loop.set_control_flow(ControlFlow::Wait);
|
||||||
}
|
}
|
||||||
UpdateMode::Reactive { wait } | UpdateMode::ReactiveLowPower { wait } => {
|
UpdateMode::Reactive { wait } | UpdateMode::ReactiveLowPower { wait } => {
|
||||||
// TODO(bug): this is unexpected behavior.
|
// TODO(bug): this is unexpected behavior.
|
||||||
|
@ -770,10 +771,8 @@ fn run_app_update_if_should(
|
||||||
// Need to verify the plateform specifics (whether this can occur in
|
// Need to verify the plateform specifics (whether this can occur in
|
||||||
// rare-but-possible cases) and replace this with a panic or a log warn!
|
// rare-but-possible cases) and replace this with a panic or a log warn!
|
||||||
if let Some(next) = runner_state.last_update.checked_add(*wait) {
|
if let Some(next) = runner_state.last_update.checked_add(*wait) {
|
||||||
runner_state.scheduled_update = Some(next);
|
|
||||||
event_loop.set_control_flow(ControlFlow::WaitUntil(next));
|
event_loop.set_control_flow(ControlFlow::WaitUntil(next));
|
||||||
} else {
|
} else {
|
||||||
runner_state.scheduled_update = None;
|
|
||||||
event_loop.set_control_flow(ControlFlow::Wait);
|
event_loop.set_control_flow(ControlFlow::Wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue