Re-work event loop run() API so it can return a Result

This re-works the portable `run()` API that consumes the `EventLoop` and
runs the loop on the calling thread until the app exits.

This can be supported across _all_ platforms and compared to the
previous `run() -> !` API is now able to return a `Result` status on all
platforms except iOS and Web. Fixes: #2709

By moving away from `run() -> !` we stop calling `std::process::exit()`
internally as a means to kill the process without returning which means
it's possible to return an exit status and applications can return from
their `main()` function normally.

This also fixes Android support where an Activity runs in a thread but
we can't assume to have full ownership of the process (other services
could be running in separate threads).

Additionally all examples have generally been updated so that `main()`
returns a `Result` from `run()`

Fixes: #2709
This commit is contained in:
Robert Bragg 2023-04-11 12:50:52 +01:00 committed by Kirill Chibisov
parent a6f414d732
commit 0d366ffbda
39 changed files with 99 additions and 123 deletions

View file

@ -3,7 +3,7 @@
mod fill;
#[cfg(any(x11_platform, macos_platform, windows_platform))]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
use std::collections::HashMap;
use raw_window_handle::HasRawWindowHandle;

View file

@ -27,7 +27,7 @@ enum Mode {
const WAIT_TIME: time::Duration = time::Duration::from_millis(100);
const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100);
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
println!("Press '1' to switch to Wait mode.");
@ -122,5 +122,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -10,7 +10,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -54,7 +54,7 @@ fn main() {
}
_ => (),
}
});
})
}
const CURSORS: &[CursorIcon] = &[

View file

@ -11,7 +11,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -73,5 +73,5 @@ fn main() {
Event::RedrawRequested(_) => fill::fill_window(&window),
_ => (),
}
});
})
}

View file

@ -1,7 +1,7 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
@ -52,7 +52,7 @@ fn main() {
}
_ => (),
}
});
})
}
#[cfg(wasm_platform)]

View file

@ -11,7 +11,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -69,7 +69,7 @@ fn main() {
}
}
_ => (),
});
})
}
fn name_windows(window_id: WindowId, switched: bool, window_1: &Window, window_2: &Window) {

View file

@ -12,7 +12,7 @@ use winit::platform::macos::WindowExtMacOS;
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -131,5 +131,5 @@ fn main() {
}
_ => {}
}
});
})
}

View file

@ -11,7 +11,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -87,5 +87,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -13,7 +13,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new()
.with_level(LevelFilter::Trace)
.init()
@ -105,5 +105,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -17,7 +17,7 @@ fn main() {
}
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
#[path = "util/fill.rs"]
mod fill;
@ -61,5 +61,5 @@ fn main() {
}
_ => (),
};
});
})
}

View file

@ -10,7 +10,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -64,5 +64,5 @@ In other words, the deltas indicate the direction in which to move the content (
}
_ => (),
}
});
})
}

View file

@ -1,7 +1,7 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
use simple_logger::SimpleLogger;

View file

@ -13,7 +13,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();

View file

@ -10,7 +10,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -41,5 +41,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -1,7 +1,7 @@
#![allow(clippy::single_match)]
#[cfg(not(wasm_platform))]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
use std::{sync::Arc, thread, time};
use simple_logger::SimpleLogger;
@ -49,7 +49,7 @@ fn main() {
}
_ => (),
}
});
})
}
#[cfg(wasm_platform)]

View file

@ -12,7 +12,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -53,5 +53,5 @@ fn main() {
}
_ => (),
};
});
})
}

View file

@ -1,9 +1,5 @@
//! Demonstrates the use of startup notifications on Linux.
fn main() {
example::main();
}
#[cfg(any(x11_platform, wayland_platform))]
#[path = "./util/fill.rs"]
mod fill;
@ -21,7 +17,7 @@ mod example {
};
use winit::window::{Window, WindowBuilder, WindowId};
pub(super) fn main() {
pub(super) fn main() -> Result<(), impl std::error::Error> {
// Create the event loop and get the activation token.
let event_loop = EventLoop::new();
let mut current_token = match event_loop.read_token_from_env() {
@ -115,13 +111,16 @@ mod example {
}
flow.set_wait();
});
})
}
}
#[cfg(not(any(x11_platform, wayland_platform)))]
mod example {
pub(super) fn main() {
println!("This example is only supported on X11 and Wayland platforms.");
}
#[cfg(any(x11_platform, wayland_platform))]
fn main() -> Result<(), impl std::error::Error> {
example::main()
}
#[cfg(not(any(x11_platform, wayland_platform)))]
fn main() {
println!("This example is only supported on X11 and Wayland platforms.");
}

View file

@ -11,7 +11,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -75,5 +75,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -16,7 +16,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -47,5 +47,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -8,7 +8,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -47,5 +47,5 @@ fn main() {
} else if let Event::RedrawRequested(_) = event {
fill::fill_window(&window);
}
});
})
}

View file

@ -10,7 +10,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -36,5 +36,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -7,7 +7,7 @@ use winit::{
window::{Fullscreen, WindowBuilder},
};
pub fn main() {
pub fn main() -> Result<(), impl std::error::Error> {
let event_loop = EventLoop::new();
let builder = WindowBuilder::new().with_title("A fantastic window!");
@ -56,7 +56,7 @@ pub fn main() {
}
_ => (),
}
});
})
}
#[cfg(wasm_platform)]
@ -72,7 +72,7 @@ mod wasm {
console_log::init_with_level(log::Level::Debug).expect("error initializing logger");
#[allow(clippy::main_recursion)]
super::main();
let _ = super::main();
}
pub fn insert_canvas_and_create_log_list(window: &Window) -> web_sys::Element {

View file

@ -47,7 +47,7 @@ This example demonstrates the desired future functionality which will possibly b
// Render once with the size info we currently have
render_circle(&canvas, window.inner_size());
event_loop.run(move |event, _, control_flow| {
let _ = event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {

View file

@ -10,7 +10,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -37,5 +37,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -14,7 +14,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -71,5 +71,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -14,7 +14,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -139,5 +139,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -13,7 +13,7 @@ const BORDER: f64 = 8.0;
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -74,7 +74,7 @@ fn main() {
fill::fill_window(&window);
}
_ => (),
});
})
}
fn cursor_direction_icon(resize_direction: Option<ResizeDirection>) -> CursorIcon {

View file

@ -12,7 +12,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
// You'll have to choose an icon size at your own discretion. On X11, the desired size varies
@ -48,7 +48,7 @@ fn main() {
} else if let Event::RedrawRequested(_) = event {
fill::fill_window(&window);
}
});
})
}
fn load_icon(path: &Path) -> Icon {

View file

@ -18,7 +18,7 @@ mod fill;
/// Prints the keyboard events characters received when option_is_alt is true versus false.
/// A left mouse click will toggle option_is_alt.
#[cfg(target_os = "macos")]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
@ -66,7 +66,7 @@ fn main() {
}
_ => (),
}
});
})
}
#[cfg(not(target_os = "macos"))]

View file

@ -11,7 +11,7 @@ use winit::{
#[path = "util/fill.rs"]
mod fill;
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();
@ -60,5 +60,5 @@ fn main() {
}
_ => (),
}
});
})
}

View file

@ -19,7 +19,7 @@ use winit::{
mod fill;
#[cfg(target_os = "macos")]
fn main() {
fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new();