Skip to content

Commit

Permalink
Allow calling winit with the 'run_return' variant of the run function (
Browse files Browse the repository at this point in the history
…#243)

This adds a new WinitConfig resource that can be used to configure the behavior of winit.
When `return_from_run` is set to `true`, `App::run()` will return on `target_os` configurations that
support it.

Closes #167.
  • Loading branch information
jakerr authored Aug 21, 2020
1 parent 505c79b commit db1bf64
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 6 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ path = "examples/app/headless.rs"
name = "plugin"
path = "examples/app/plugin.rs"

[[example]]
name = "return_after_run"
path = "examples/app/return_after_run.rs"

[[example]]
name = "thread_pool_resources"
path = "examples/app/thread_pool_resources.rs"
Expand Down Expand Up @@ -221,4 +225,4 @@ path = "examples/window/multiple_windows.rs"

[[example]]
name = "window_settings"
path = "examples/window/window_settings.rs"
path = "examples/window/window_settings.rs"
68 changes: 63 additions & 5 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
mod converters;
mod winit_config;
mod winit_windows;
pub use winit_windows::*;

use bevy_input::{
keyboard::KeyboardInput,
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
};
pub use winit_config::*;
pub use winit_windows::*;

use bevy_app::{prelude::*, AppExit};
use bevy_ecs::Resources;
use bevy_math::Vec2;
use bevy_window::{
CreateWindow, CursorMoved, Window, WindowCloseRequested, WindowCreated, WindowResized, Windows,
};
use event::Event;
use winit::{
event,
event::{DeviceEvent, WindowEvent},
Expand All @@ -33,8 +35,51 @@ impl Plugin for WinitPlugin {
}
}

fn run<F>(event_loop: EventLoop<()>, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, ()>, &EventLoopWindowTarget<()>, &mut ControlFlow),
{
event_loop.run(event_handler)
}

// TODO: It may be worth moving this cfg into a procedural macro so that it can be referenced by
// a single name instead of being copied around.
// https://gist.github.com/jakerr/231dee4a138f7a5f25148ea8f39b382e seems to work.
#[cfg(any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
fn run_return<F>(event_loop: &mut EventLoop<()>, event_handler: F)
where
F: FnMut(Event<'_, ()>, &EventLoopWindowTarget<()>, &mut ControlFlow),
{
use winit::platform::desktop::EventLoopExtDesktop;
event_loop.run_return(event_handler)
}

#[cfg(not(any(
target_os = "windows",
target_os = "macos",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)))]
fn run_return<F>(event_loop: &mut EventLoop<()>, event_handler: F)
where
F: FnMut(Event<'_, ()>, &EventLoopWindowTarget<()>, &mut ControlFlow),
{
panic!("Run return is not supported on this platform!")
}

pub fn winit_runner(mut app: App) {
let event_loop = EventLoop::new();
let mut event_loop = EventLoop::new();
let mut create_window_event_reader = EventReader::<CreateWindow>::default();
let mut app_exit_event_reader = EventReader::<AppExit>::default();

Expand All @@ -45,7 +90,15 @@ pub fn winit_runner(mut app: App) {
);

log::debug!("Entering winit event loop");
event_loop.run(move |event, event_loop, control_flow| {

let should_return_from_run = app
.resources
.get::<WinitConfig>()
.map_or(false, |config| config.return_from_run);

let event_handler = move |event: Event<()>,
event_loop: &EventLoopWindowTarget<()>,
control_flow: &mut ControlFlow| {
*control_flow = if cfg!(feature = "metal-auto-capture") {
ControlFlow::Exit
} else {
Expand Down Expand Up @@ -160,7 +213,12 @@ pub fn winit_runner(mut app: App) {
}
_ => (),
}
});
};
if should_return_from_run {
run_return(&mut event_loop, event_handler);
} else {
run(event_loop, event_handler);
}
}

fn handle_create_window_events(
Expand Down
15 changes: 15 additions & 0 deletions crates/bevy_winit/src/winit_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// A resource for configuring usage of the `rust_winit` library.
#[derive(Default)]
pub struct WinitConfig {
/// Configures the winit library to return control to the main thread after
/// the [run](bevy_app::App::run) loop is exited. Winit strongly recommends
/// avoiding this when possible. Before using this please read and understand
/// the [caveats](winit::platform::desktop::EventLoopExtDesktop::run_return)
/// in the winit documentation.
///
/// This feature is only available on desktop `target_os` configurations.
/// Namely `windows`, `macos`, `linux`, `dragonfly`, `freebsd`, `netbsd`, and
/// `openbsd`. If set to true on an unsupported platform
/// [run](bevy_app::App::run) will panic.
pub return_from_run: bool,
}
21 changes: 21 additions & 0 deletions examples/app/return_after_run.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use bevy::{prelude::*, render::pass::ClearColor, winit::WinitConfig};

fn main() {
println!("Running first App.");
App::build()
.add_resource(WinitConfig {
return_from_run: true,
})
.add_resource(ClearColor(Color::rgb(0.2, 0.2, 0.8)))
.add_default_plugins()
.run();
println!("Running another App.");
App::build()
.add_resource(WinitConfig {
return_from_run: true,
})
.add_resource(ClearColor(Color::rgb(0.2, 0.8, 0.2)))
.add_default_plugins()
.run();
println!("Done.");
}

0 comments on commit db1bf64

Please sign in to comment.