bevy/crates/bevy_winit/src/winit_config.rs
Stephen Martindale f0c504947c Docs: App::run() might never return; effect of WinitSettings::return_from_run. (#7228)
# Objective

See:

- https://github.com/bevyengine/bevy/issues/7067#issuecomment-1381982285
  - (This does not fully close that issue in my opinion.)
- https://discord.com/channels/691052431525675048/1063454009769340989

## Solution

This merge request adds documentation:

1. Alert users to the fact that `App::run()` might never return and code placed after it might never be executed.
2. Makes `winit::WinitSettings::return_from_run` discoverable.
3. Better explains why `winit::WinitSettings::return_from_run` is discouraged and better links to up-stream docs. on that topic.
4. Adds notes to the `app/return_after_run.rs` example which otherwise promotes a feature that carries caveats.

Furthermore, w.r.t `winit::WinitSettings::return_from_run`:

- Broken links to `winit` docs are fixed.
- Links now point to BOTH `EventLoop::run()` and `EventLoopExtRunReturn::run_return()` which are the salient up-stream pages and make more sense, taken together.
- Collateral damage: "Supported platforms" heading; disambiguation of "run" → `App::run()`; links.
   
## Future Work

I deliberately structured the "`run()` might not return" section under `App::run()` to allow for alternative patterns (e.g. `AppExit` event, `WindowClosed` event) to be listed or mentioned, beneath it, in the future.
2023-01-18 23:02:38 +00:00

114 lines
4.9 KiB
Rust

use bevy_ecs::system::Resource;
use bevy_utils::Duration;
/// A resource for configuring usage of the `rust_winit` library.
#[derive(Debug, Resource)]
pub struct WinitSettings {
/// Configures `winit` to return control to the caller after exiting the
/// event loop, enabling [`App::run()`](bevy_app::App::run()) to return.
///
/// By default, [`return_from_run`](Self::return_from_run) is `false` and *Bevy*
/// will use `winit`'s
/// [`EventLoop::run()`](https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run)
/// to initiate the event loop.
/// [`EventLoop::run()`](https://docs.rs/winit/latest/winit/event_loop/struct.EventLoop.html#method.run)
/// will never return but will terminate the process after the event loop exits.
///
/// Setting [`return_from_run`](Self::return_from_run) to `true` will cause *Bevy*
/// to use `winit`'s
/// [`EventLoopExtRunReturn::run_return()`](https://docs.rs/winit/latest/winit/platform/run_return/trait.EventLoopExtRunReturn.html#tymethod.run_return)
/// instead which is strongly discouraged by the `winit` authors.
///
/// # Supported platforms
///
/// This feature is only available on the following desktop `target_os` configurations:
/// `windows`, `macos`, `linux`, `dragonfly`, `freebsd`, `netbsd`, and `openbsd`.
///
/// Setting [`return_from_run`](Self::return_from_run) to `true` on
/// unsupported platforms will cause [`App::run()`](bevy_app::App::run()) to panic!
pub return_from_run: bool,
/// Configures how the winit event loop updates while the window is focused.
pub focused_mode: UpdateMode,
/// Configures how the winit event loop updates while the window is *not* focused.
pub unfocused_mode: UpdateMode,
}
impl WinitSettings {
/// Configure winit with common settings for a game.
pub fn game() -> Self {
WinitSettings::default()
}
/// Configure winit with common settings for a desktop application.
pub fn desktop_app() -> Self {
WinitSettings {
focused_mode: UpdateMode::Reactive {
max_wait: Duration::from_secs(5),
},
unfocused_mode: UpdateMode::ReactiveLowPower {
max_wait: Duration::from_secs(60),
},
..Default::default()
}
}
/// Gets the configured `UpdateMode` depending on whether the window is focused or not
pub fn update_mode(&self, focused: bool) -> &UpdateMode {
match focused {
true => &self.focused_mode,
false => &self.unfocused_mode,
}
}
}
impl Default for WinitSettings {
fn default() -> Self {
WinitSettings {
return_from_run: false,
focused_mode: UpdateMode::Continuous,
unfocused_mode: UpdateMode::Continuous,
}
}
}
/// Configure how the winit event loop should update.
#[derive(Debug)]
pub enum UpdateMode {
/// The event loop will update continuously, running as fast as possible.
Continuous,
/// The event loop will only update if there is a winit event, a redraw is requested, or the
/// maximum wait time has elapsed.
///
/// ## Note
///
/// Once the app has executed all bevy systems and reaches the end of the event loop, there is
/// no way to force the app to wake and update again, unless a `winit` event (such as user
/// input, or the window being resized) is received or the time limit is reached.
Reactive {
/// The maximum time to wait before the event loop runs again.
///
/// Note that Bevy will wait indefinitely if the duration is too high (such as [`Duration::MAX`]).
max_wait: Duration,
},
/// The event loop will only update if there is a winit event from direct interaction with the
/// window (e.g. mouseover), a redraw is requested, or the maximum wait time has elapsed.
///
/// ## Note
///
/// Once the app has executed all bevy systems and reaches the end of the event loop, there is
/// no way to force the app to wake and update again, unless a `winit` event (such as user
/// input, or the window being resized) is received or the time limit is reached.
///
/// ## Differences from [`UpdateMode::Reactive`]
///
/// Unlike [`UpdateMode::Reactive`], this mode will ignore winit events that aren't directly
/// caused by interaction with the window. For example, you might want to use this mode when the
/// window is not focused, to only re-draw your bevy app when the cursor is over the window, but
/// not when the mouse moves somewhere else on the screen. This helps to significantly reduce
/// power consumption by only updated the app when absolutely necessary.
ReactiveLowPower {
/// The maximum time to wait before the event loop runs again.
///
/// Note that Bevy will wait indefinitely if the duration is too high (such as [`Duration::MAX`]).
max_wait: Duration,
},
}