diff --git a/CHANGELOG.md b/CHANGELOG.md index 429d09a4..99053d11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased +- **Breaking:** `WINIT_UNIX_BACKEND` was removed in favor of standard `WAYLAND_DISPLAY` and `DISPLAY` variables. +- **Breaking:** `EventLoop::new` and `EventLoopBuilder::build` now return `Result` - On X11, set `visual_id` in returned `raw-window-handle`. - **Breaking:** on Wayland, dispatching user created wayland queue won't wake up the loop unless winit has event to send back. - Removed platform-specific extensions that should be retrieved through `raw-window-handle` trait implementations instead: @@ -51,7 +53,7 @@ And please only add new entries to the top of this list, right below the `# Unre - On Web, remove unnecessary `Window::is_dark_mode()`, which was replaced with `Window::theme()`. - On Web, add `WindowBuilderExtWebSys::with_append()` to append the canvas element to the web page on creation. - On Windows, add `drag_resize_window` method support. -- **Breaking** `run() ->!` has been replaced by `run() -> Result<(), RunLoopError>` for returning errors without calling `std::process::exit()` ([#2767](https://github.com/rust-windowing/winit/pull/2767)) +- **Breaking** `run() ->!` has been replaced by `run() -> Result<(), EventLoopError>` for returning errors without calling `std::process::exit()` ([#2767](https://github.com/rust-windowing/winit/pull/2767)) - **Breaking** Removed `EventLoopExtRunReturn` / `run_return` in favor of `EventLoopExtPumpEvents` / `pump_events` and `EventLoopExtRunOnDemand` / `run_ondemand` ([#2767](https://github.com/rust-windowing/winit/pull/2767)) - `RedrawRequested` is no longer guaranteed to be emitted after `MainEventsCleared`, it is now platform-specific when the event is emitted after being requested via `redraw_request()`. - On Windows, `RedrawRequested` is now driven by `WM_PAINT` messages which are requested via `redraw_request()` diff --git a/examples/child_window.rs b/examples/child_window.rs index 9d3bc053..ef28757d 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -36,7 +36,7 @@ fn main() -> Result<(), impl std::error::Error> { let mut windows = HashMap::new(); - let event_loop: EventLoop<()> = EventLoop::new(); + let event_loop: EventLoop<()> = EventLoop::new().unwrap(); let parent_window = WindowBuilder::new() .with_title("parent window") .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) diff --git a/examples/control_flow.rs b/examples/control_flow.rs index cde56265..8ed24f4f 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -36,7 +36,7 @@ fn main() -> Result<(), impl std::error::Error> { println!("Press 'R' to toggle request_redraw() calls."); println!("Press 'Esc' to close the window."); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.") .build(&event_loop) diff --git a/examples/cursor.rs b/examples/cursor.rs index e7d3b9d5..bba0d012 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -12,7 +12,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); window.set_title("A fantastic window!"); diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index b69ab47c..99a42825 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -13,7 +13,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("Super Cursor Grab'n'Hide Simulator 9000") diff --git a/examples/custom_events.rs b/examples/custom_events.rs index 2e8f5472..ecadebf5 100644 --- a/examples/custom_events.rs +++ b/examples/custom_events.rs @@ -18,7 +18,9 @@ fn main() -> Result<(), impl std::error::Error> { } SimpleLogger::new().init().unwrap(); - let event_loop = EventLoopBuilder::::with_user_event().build(); + let event_loop = EventLoopBuilder::::with_user_event() + .build() + .unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/drag_window.rs b/examples/drag_window.rs index 55056001..97ed5c8d 100644 --- a/examples/drag_window.rs +++ b/examples/drag_window.rs @@ -13,7 +13,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window_1 = WindowBuilder::new().build(&event_loop).unwrap(); let window_2 = WindowBuilder::new().build(&event_loop).unwrap(); diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 675ad8ff..4ff40885 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -15,7 +15,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut decorations = true; let mut minimized = false; diff --git a/examples/handling_close.rs b/examples/handling_close.rs index 5fa90283..578e9539 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -13,7 +13,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("Your faithful window") diff --git a/examples/ime.rs b/examples/ime.rs index 319e0615..fe33fa6c 100644 --- a/examples/ime.rs +++ b/examples/ime.rs @@ -24,7 +24,7 @@ fn main() -> Result<(), impl std::error::Error> { println!("Press F2 to toggle IME. See the documentation of `set_ime_allowed` for more info"); println!("Press F3 to cycle through IME purposes."); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_inner_size(winit::dpi::LogicalSize::new(256f64, 128f64)) diff --git a/examples/key_binding.rs b/examples/key_binding.rs index ef5d5319..5f438a0e 100644 --- a/examples/key_binding.rs +++ b/examples/key_binding.rs @@ -22,7 +22,7 @@ fn main() -> Result<(), impl std::error::Error> { mod fill; simple_logger::SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_inner_size(LogicalSize::new(400.0, 200.0)) diff --git a/examples/monitor_list.rs b/examples/monitor_list.rs index 23081b63..b156028d 100644 --- a/examples/monitor_list.rs +++ b/examples/monitor_list.rs @@ -7,7 +7,7 @@ use winit::{event_loop::EventLoop, window::WindowBuilder}; fn main() { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); if let Some(mon) = window.primary_monitor() { diff --git a/examples/mouse_wheel.rs b/examples/mouse_wheel.rs index 38d06aff..9c32aa35 100644 --- a/examples/mouse_wheel.rs +++ b/examples/mouse_wheel.rs @@ -12,7 +12,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("Mouse Wheel events") diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index c1557821..290cb51a 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), impl std::error::Error> { const WINDOW_SIZE: PhysicalSize = PhysicalSize::new(600, 400); SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut window_senders = HashMap::with_capacity(WINDOW_COUNT); for _ in 0..WINDOW_COUNT { let window = WindowBuilder::new() diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 7fcb724b..b4e82cdc 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -15,7 +15,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut windows = HashMap::new(); for _ in 0..3 { diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index a064cd39..fe3810e6 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -12,7 +12,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/request_redraw_threaded.rs b/examples/request_redraw_threaded.rs index 2010f96e..173b399f 100644 --- a/examples/request_redraw_threaded.rs +++ b/examples/request_redraw_threaded.rs @@ -15,7 +15,7 @@ fn main() -> Result<(), impl std::error::Error> { mod fill; SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = { let window = WindowBuilder::new() diff --git a/examples/resizable.rs b/examples/resizable.rs index ecec14b2..c6d0d095 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -14,7 +14,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut resizable = false; diff --git a/examples/startup_notification.rs b/examples/startup_notification.rs index fdd68d51..5b684b87 100644 --- a/examples/startup_notification.rs +++ b/examples/startup_notification.rs @@ -19,7 +19,7 @@ mod example { pub(super) fn main() -> Result<(), impl std::error::Error> { // Create the event loop and get the activation token. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut current_token = match event_loop.read_token_from_env() { Some(token) => Some(token), None => { diff --git a/examples/theme.rs b/examples/theme.rs index b3dac443..485d2481 100644 --- a/examples/theme.rs +++ b/examples/theme.rs @@ -13,7 +13,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/timer.rs b/examples/timer.rs index 13fceb51..329c36b8 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -18,7 +18,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/touchpad_gestures.rs b/examples/touchpad_gestures.rs index 0cca2c2c..44f2eee1 100644 --- a/examples/touchpad_gestures.rs +++ b/examples/touchpad_gestures.rs @@ -10,7 +10,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("Touchpad gestures") diff --git a/examples/transparent.rs b/examples/transparent.rs index b093867d..9d3a470a 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -12,7 +12,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_decorations(false) diff --git a/examples/video_modes.rs b/examples/video_modes.rs index 3b262c7b..75acdbd4 100644 --- a/examples/video_modes.rs +++ b/examples/video_modes.rs @@ -5,7 +5,7 @@ use winit::event_loop::EventLoop; fn main() { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let monitor = match event_loop.primary_monitor() { Some(monitor) => monitor, None => { diff --git a/examples/web.rs b/examples/web.rs index f8237a7b..b8ba1671 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -8,7 +8,7 @@ use winit::{ }; pub fn main() -> Result<(), impl std::error::Error> { - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let builder = WindowBuilder::new().with_title("A fantastic window!"); #[cfg(wasm_platform)] diff --git a/examples/web_aspect_ratio.rs b/examples/web_aspect_ratio.rs index e0f5ba16..2b19f776 100644 --- a/examples/web_aspect_ratio.rs +++ b/examples/web_aspect_ratio.rs @@ -31,7 +31,7 @@ This example demonstrates the desired future functionality which will possibly b #[wasm_bindgen(start)] pub fn run() { console_log::init_with_level(log::Level::Debug).expect("error initializing logger"); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window.rs b/examples/window.rs index 0c2729ec..21be03f0 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -12,7 +12,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window_buttons.rs b/examples/window_buttons.rs index b531531c..c7f04a34 100644 --- a/examples/window_buttons.rs +++ b/examples/window_buttons.rs @@ -16,7 +16,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 5c7f2326..e7283942 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -16,7 +16,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window_drag_resize.rs b/examples/window_drag_resize.rs index 3232c4c8..73908cac 100644 --- a/examples/window_drag_resize.rs +++ b/examples/window_drag_resize.rs @@ -15,7 +15,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0)) diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 6e65f348..1811812e 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -23,7 +23,7 @@ fn main() -> Result<(), impl std::error::Error> { let icon = load_icon(Path::new(path)); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("An iconic window!") diff --git a/examples/window_ondemand.rs b/examples/window_ondemand.rs index 0a59f4fc..faa63e17 100644 --- a/examples/window_ondemand.rs +++ b/examples/window_ondemand.rs @@ -8,7 +8,7 @@ fn main() -> Result<(), impl std::error::Error> { use simple_logger::SimpleLogger; use winit::{ - error::RunLoopError, + error::EventLoopError, event::{Event, WindowEvent}, event_loop::EventLoop, platform::run_ondemand::EventLoopExtRunOnDemand, @@ -25,9 +25,9 @@ fn main() -> Result<(), impl std::error::Error> { } SimpleLogger::new().init().unwrap(); - let mut event_loop = EventLoop::new(); + let mut event_loop = EventLoop::new().unwrap(); - fn run_app(event_loop: &mut EventLoop<()>, idx: usize) -> Result<(), RunLoopError> { + fn run_app(event_loop: &mut EventLoop<()>, idx: usize) -> Result<(), EventLoopError> { let mut app = App::default(); event_loop.run_ondemand(move |event, event_loop, control_flow| { diff --git a/examples/window_option_as_alt.rs b/examples/window_option_as_alt.rs index 60c6fce3..a28374be 100644 --- a/examples/window_option_as_alt.rs +++ b/examples/window_option_as_alt.rs @@ -19,7 +19,7 @@ mod fill; /// A left mouse click will toggle option_is_alt. #[cfg(target_os = "macos")] fn main() -> Result<(), impl std::error::Error> { - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window_pump_events.rs b/examples/window_pump_events.rs index 2de01bc8..0317981a 100644 --- a/examples/window_pump_events.rs +++ b/examples/window_pump_events.rs @@ -22,7 +22,7 @@ fn main() -> std::process::ExitCode { #[path = "util/fill.rs"] mod fill; - let mut event_loop = EventLoop::new(); + let mut event_loop = EventLoop::new().unwrap(); SimpleLogger::new().init().unwrap(); let window = WindowBuilder::new() diff --git a/examples/window_resize_increments.rs b/examples/window_resize_increments.rs index 0fcf4b9c..6b04072d 100644 --- a/examples/window_resize_increments.rs +++ b/examples/window_resize_increments.rs @@ -13,7 +13,7 @@ mod fill; fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title("A fantastic window!") diff --git a/examples/window_tabbing.rs b/examples/window_tabbing.rs index 1989a8f3..732a5b62 100644 --- a/examples/window_tabbing.rs +++ b/examples/window_tabbing.rs @@ -21,7 +21,7 @@ mod fill; #[cfg(target_os = "macos")] fn main() -> Result<(), impl std::error::Error> { SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut windows = HashMap::new(); let window = Window::new(&event_loop).unwrap(); diff --git a/examples/x11_embed.rs b/examples/x11_embed.rs index 37014ea9..220389be 100644 --- a/examples/x11_embed.rs +++ b/examples/x11_embed.rs @@ -23,7 +23,7 @@ mod imple { .parse::()?; SimpleLogger::new().init().unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new()?; let window = WindowBuilder::new() .with_title("An embedded window!") diff --git a/src/error.rs b/src/error.rs index 42a3f43c..92468620 100644 --- a/src/error.rs +++ b/src/error.rs @@ -30,17 +30,25 @@ pub struct OsError { /// A general error that may occur while running the Winit event loop #[derive(Debug)] -pub enum RunLoopError { +pub enum EventLoopError { /// The operation is not supported by the backend. NotSupported(NotSupportedError), /// The OS cannot perform the operation. Os(OsError), /// The event loop can't be re-run while it's already running AlreadyRunning, + /// The event loop can't be re-created. + RecreationAttempt, /// Application has exit with an error status. ExitFailure(i32), } +impl From for EventLoopError { + fn from(value: OsError) -> Self { + Self::Os(value) + } +} + impl NotSupportedError { #[inline] #[allow(dead_code)] @@ -94,13 +102,14 @@ impl fmt::Display for NotSupportedError { } } -impl fmt::Display for RunLoopError { +impl fmt::Display for EventLoopError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self { - RunLoopError::AlreadyRunning => write!(f, "EventLoop is already running"), - RunLoopError::NotSupported(e) => e.fmt(f), - RunLoopError::Os(e) => e.fmt(f), - RunLoopError::ExitFailure(status) => write!(f, "Exit Failure: {status}"), + EventLoopError::AlreadyRunning => write!(f, "EventLoop is already running"), + EventLoopError::RecreationAttempt => write!(f, "EventLoop can't be recreated"), + EventLoopError::NotSupported(e) => e.fmt(f), + EventLoopError::Os(e) => e.fmt(f), + EventLoopError::ExitFailure(status) => write!(f, "Exit Failure: {status}"), } } } @@ -108,7 +117,7 @@ impl fmt::Display for RunLoopError { impl error::Error for OsError {} impl error::Error for ExternalError {} impl error::Error for NotSupportedError {} -impl error::Error for RunLoopError {} +impl error::Error for EventLoopError {} #[cfg(test)] mod tests { diff --git a/src/event_loop.rs b/src/event_loop.rs index 0986b3aa..b4b10f16 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -18,7 +18,7 @@ use std::time::{Duration, Instant}; #[cfg(wasm_platform)] use web_time::{Duration, Instant}; -use crate::error::RunLoopError; +use crate::error::EventLoopError; use crate::{event::Event, monitor::MonitorHandle, platform_impl}; /// Provides a way to retrieve events from the system and from the windows that were registered to @@ -88,23 +88,23 @@ impl EventLoopBuilder { /// ***For cross-platform compatibility, the [`EventLoop`] must be created on the main thread, /// and only once per application.*** /// - /// Attempting to create the event loop on a different thread, or multiple event loops in - /// the same application, will panic. This restriction isn't - /// strictly necessary on all platforms, but is imposed to eliminate any nasty surprises when - /// porting to platforms that require it. `EventLoopBuilderExt::any_thread` functions are exposed - /// in the relevant [`platform`] module if the target platform supports creating an event loop on - /// any thread. - /// /// Calling this function will result in display backend initialisation. /// + /// ## Panics + /// + /// Attempting to create the event loop off the main thread will panic. This + /// restriction isn't strictly necessary on all platforms, but is imposed to + /// eliminate any nasty surprises when porting to platforms that require it. + /// `EventLoopBuilderExt::any_thread` functions are exposed in the relevant + /// [`platform`] module if the target platform supports creating an event + /// loop on any thread. + /// /// ## Platform-specific /// - /// - **Linux:** Backend type can be controlled using an environment variable - /// `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`. - /// If it is not set, winit will try to connect to a Wayland connection, and if that fails, - /// will fall back on X11. If this variable is set with any other value, winit will panic. - /// - **Android:** Must be configured with an `AndroidApp` from `android_main()` by calling - /// [`.with_android_app(app)`] before calling `.build()`. + /// - **Wayland/X11:** to prevent running under `Wayland` or `X11` unset `WAYLAND_DISPLAY` + /// or `DISPLAY` respectively when building the event loop. + /// - **Android:** must be configured with an `AndroidApp` from `android_main()` by calling + /// [`.with_android_app(app)`] before calling `.build()`, otherwise it'll panic. /// /// [`platform`]: crate::platform #[cfg_attr( @@ -116,17 +116,17 @@ impl EventLoopBuilder { doc = "[`.with_android_app(app)`]: #only-available-on-android" )] #[inline] - pub fn build(&mut self) -> EventLoop { + pub fn build(&mut self) -> Result, EventLoopError> { if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) { - panic!("Creating EventLoop multiple times is not supported."); + return Err(EventLoopError::RecreationAttempt); } // Certain platforms accept a mutable reference in their API. #[allow(clippy::unnecessary_mut_passed)] - EventLoop { - event_loop: platform_impl::EventLoop::new(&mut self.platform_specific), + Ok(EventLoop { + event_loop: platform_impl::EventLoop::new(&mut self.platform_specific)?, _marker: PhantomData, - } + }) } #[cfg(wasm_platform)] @@ -269,20 +269,14 @@ impl EventLoop<()> { /// /// [`EventLoopBuilder::new().build()`]: EventLoopBuilder::build #[inline] - pub fn new() -> EventLoop<()> { + pub fn new() -> Result, EventLoopError> { EventLoopBuilder::new().build() } } -impl Default for EventLoop<()> { - fn default() -> Self { - Self::new() - } -} - impl EventLoop { #[deprecated = "Use `EventLoopBuilder::::with_user_event().build()` instead."] - pub fn with_user_event() -> EventLoop { + pub fn with_user_event() -> Result, EventLoopError> { EventLoopBuilder::::with_user_event().build() } @@ -315,7 +309,7 @@ impl EventLoop { /// [`ControlFlow`]: crate::event_loop::ControlFlow #[inline] #[cfg(not(all(wasm_platform, target_feature = "exception-handling")))] - pub fn run(self, event_handler: F) -> Result<(), RunLoopError> + pub fn run(self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { diff --git a/src/lib.rs b/src/lib.rs index c2e27acb..ae1281ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ //! //! ```no_run //! use winit::event_loop::EventLoop; -//! let event_loop = EventLoop::new(); +//! let event_loop = EventLoop::new().unwrap(); //! ``` //! //! Once this is done there are two ways to create a [`Window`]: @@ -48,7 +48,7 @@ //! window::WindowBuilder, //! }; //! -//! let event_loop = EventLoop::new(); +//! let event_loop = EventLoop::new().unwrap(); //! let window = WindowBuilder::new().build(&event_loop).unwrap(); //! //! event_loop.run(move |event, _, control_flow| { diff --git a/src/platform/pump_events.rs b/src/platform/pump_events.rs index d9bdf8f4..fa970ca1 100644 --- a/src/platform/pump_events.rs +++ b/src/platform/pump_events.rs @@ -53,7 +53,7 @@ pub trait EventLoopExtPumpEvents { /// # platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, /// # window::WindowBuilder, /// # }; - /// let mut event_loop = EventLoop::new(); + /// let mut event_loop = EventLoop::new().unwrap(); /// # /// # SimpleLogger::new().init().unwrap(); /// let window = WindowBuilder::new() diff --git a/src/platform/run_ondemand.rs b/src/platform/run_ondemand.rs index c1e36326..031b670c 100644 --- a/src/platform/run_ondemand.rs +++ b/src/platform/run_ondemand.rs @@ -1,5 +1,5 @@ use crate::{ - error::RunLoopError, + error::EventLoopError, event::Event, event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, }; @@ -57,7 +57,7 @@ pub trait EventLoopExtRunOnDemand { /// polled to ask for new events. Events are delivered via callbacks based /// on an event loop that is internal to the browser itself. /// - **iOS:** It's not possible to stop and start an `NSApplication` repeatedly on iOS. - fn run_ondemand(&mut self, event_handler: F) -> Result<(), RunLoopError> + fn run_ondemand(&mut self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow); } @@ -65,7 +65,7 @@ pub trait EventLoopExtRunOnDemand { impl EventLoopExtRunOnDemand for EventLoop { type UserEvent = T; - fn run_ondemand(&mut self, event_handler: F) -> Result<(), RunLoopError> + fn run_ondemand(&mut self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 51f63b9f..5cbd2fe3 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -130,7 +130,7 @@ pub trait WindowBuilderExtX11 { /// use winit::window::WindowBuilder; /// use winit::platform::x11::{XWindow, WindowBuilderExtX11}; /// # fn main() -> Result<(), Box> { - /// let event_loop = winit::event_loop::EventLoop::new(); + /// let event_loop = winit::event_loop::EventLoop::new().unwrap(); /// let parent_window_id = std::env::args().nth(1).unwrap().parse::()?; /// let window = WindowBuilder::new() /// .with_embed_parent_window(parent_window_id) diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index a0a8664a..aa4003b8 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -29,7 +29,7 @@ use crate::{ self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowLevel, }, }; -use crate::{error::RunLoopError, platform_impl::Fullscreen}; +use crate::{error::EventLoopError, platform_impl::Fullscreen}; mod keycodes; @@ -186,13 +186,15 @@ fn sticky_exit_callback( } impl EventLoop { - pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Self { + pub(crate) fn new( + attributes: &PlatformSpecificEventLoopAttributes, + ) -> Result { let (user_events_sender, user_events_receiver) = mpsc::channel(); let android_app = attributes.android_app.as_ref().expect("An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on Android"); let redraw_flag = SharedFlag::new(); - Self { + Ok(Self { android_app: android_app.clone(), window_target: event_loop::EventLoopWindowTarget { p: EventLoopWindowTarget { @@ -215,7 +217,7 @@ impl EventLoop { cause: StartCause::Init, ignore_volume_keys: attributes.ignore_volume_keys, combining_accent: None, - } + }) } fn single_iteration(&mut self, main_event: Option>, callback: &mut F) @@ -533,19 +535,19 @@ impl EventLoop { input_status } - pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> + pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { self.run_ondemand(event_handler) } - pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { if self.loop_running { - return Err(RunLoopError::AlreadyRunning); + return Err(EventLoopError::AlreadyRunning); } loop { @@ -554,7 +556,7 @@ impl EventLoop { break Ok(()); } PumpStatus::Exit(code) => { - break Err(RunLoopError::ExitFailure(code)); + break Err(EventLoopError::ExitFailure(code)); } _ => { continue; diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index 070f0cb3..88a08182 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -19,11 +19,9 @@ use objc2::rc::Id; use objc2::ClassType; use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle}; -use super::uikit::{UIApplication, UIApplicationMain, UIDevice, UIScreen}; -use super::view::WinitUIWindow; -use super::{app_state, monitor, view, MonitorHandle}; use crate::{ dpi::LogicalSize, + error::EventLoopError, event::Event, event_loop::{ ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget, @@ -31,6 +29,10 @@ use crate::{ platform::ios::Idiom, }; +use super::uikit::{UIApplication, UIApplicationMain, UIDevice, UIScreen}; +use super::view::WinitUIWindow; +use super::{app_state, monitor, view, MonitorHandle}; + #[derive(Debug)] pub(crate) enum EventWrapper { StaticEvent(Event), @@ -75,7 +77,9 @@ pub struct EventLoop { pub(crate) struct PlatformSpecificEventLoopAttributes {} impl EventLoop { - pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> EventLoop { + pub(crate) fn new( + _: &PlatformSpecificEventLoopAttributes, + ) -> Result, EventLoopError> { assert_main_thread!("`EventLoop` can only be created on the main thread on iOS"); static mut SINGLETON_INIT: bool = false; @@ -93,7 +97,7 @@ impl EventLoop { // this line sets up the main run loop before `UIApplicationMain` setup_control_flow_observers(); - EventLoop { + Ok(EventLoop { window_target: RootEventLoopWindowTarget { p: EventLoopWindowTarget { receiver, @@ -101,7 +105,7 @@ impl EventLoop { }, _marker: PhantomData, }, - } + }) } pub fn run(self, event_handler: F) -> ! diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 611f73a7..6b9cd25d 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -3,33 +3,22 @@ #[cfg(all(not(x11_platform), not(wayland_platform)))] compile_error!("Please select a feature to build for unix: `x11`, `wayland`"); -#[cfg(wayland_platform)] -use std::error::Error; - +use std::sync::Arc; +use std::time::Duration; use std::{collections::VecDeque, env, fmt}; #[cfg(x11_platform)] -use std::{ - ffi::CStr, - mem::MaybeUninit, - os::raw::*, - sync::{Arc, Mutex}, -}; +use std::{ffi::CStr, mem::MaybeUninit, os::raw::*, sync::Mutex}; #[cfg(x11_platform)] use once_cell::sync::Lazy; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use smol_str::SmolStr; -use std::time::Duration; -#[cfg(x11_platform)] -pub use self::x11::XNotSupported; -#[cfg(x11_platform)] -use self::x11::{util::WindowType as XWindowType, X11Error, XConnection, XError}; #[cfg(x11_platform)] use crate::platform::x11::XlibErrorHook; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - error::{ExternalError, NotSupportedError, OsError as RootOsError, RunLoopError}, + error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError}, event::{Event, KeyEvent}, event_loop::{ AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed, @@ -46,6 +35,10 @@ use crate::{ UserAttentionType, WindowAttributes, WindowButtons, WindowLevel, }, }; +#[cfg(x11_platform)] +pub use x11::XNotSupported; +#[cfg(x11_platform)] +use x11::{util::WindowType as XWindowType, X11Error, XConnection, XError}; pub(crate) use crate::icon::RgbaIcon as PlatformIcon; pub(crate) use crate::platform_impl::Fullscreen; @@ -56,15 +49,6 @@ pub mod wayland; #[cfg(x11_platform)] pub mod x11; -/// Environment variable specifying which backend should be used on unix platform. -/// -/// Legal values are x11 and wayland. If this variable is set only the named backend -/// will be tried by winit. If it is not set, winit will try to connect to a wayland connection, -/// and if it fails will fallback on x11. -/// -/// If this variable is set with any other value, winit will panic. -const BACKEND_PREFERENCE_ENV_VAR: &str = "WINIT_UNIX_BACKEND"; - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub(crate) enum Backend { #[cfg(x11_platform)] @@ -136,23 +120,21 @@ pub(crate) static X11_BACKEND: Lazy, XNotSupported #[derive(Debug, Clone)] pub enum OsError { + Misc(&'static str), #[cfg(x11_platform)] XError(Arc), - #[cfg(x11_platform)] - XMisc(&'static str), #[cfg(wayland_platform)] - WaylandMisc(&'static str), + WaylandError(Arc), } impl fmt::Display for OsError { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { + OsError::Misc(e) => _f.pad(e), #[cfg(x11_platform)] OsError::XError(ref e) => fmt::Display::fmt(e, _f), - #[cfg(x11_platform)] - OsError::XMisc(e) => _f.pad(e), #[cfg(wayland_platform)] - OsError::WaylandMisc(e) => _f.pad(e), + OsError::WaylandError(ref e) => fmt::Display::fmt(e, _f), } } } @@ -748,7 +730,9 @@ impl Clone for EventLoopProxy { } impl EventLoop { - pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Self { + pub(crate) fn new( + attributes: &PlatformSpecificEventLoopAttributes, + ) -> Result { if !attributes.any_thread && !is_main_thread() { panic!( "Initializing the event loop outside of the main thread is a significant \ @@ -758,65 +742,26 @@ impl EventLoop { ); } - #[cfg(x11_platform)] - if attributes.forced_backend == Some(Backend::X) { - // TODO: Propagate - return EventLoop::new_x11_any_thread().unwrap(); - } - + // NOTE: Wayland first because of X11 could be present under wayland as well. #[cfg(wayland_platform)] - if attributes.forced_backend == Some(Backend::Wayland) { - // TODO: Propagate - return EventLoop::new_wayland_any_thread().expect("failed to open Wayland connection"); + if attributes.forced_backend == Some(Backend::Wayland) + || env::var("WAYLAND_DISPLAY").is_ok() + { + return EventLoop::new_wayland_any_thread().map_err(Into::into); } - if let Ok(env_var) = env::var(BACKEND_PREFERENCE_ENV_VAR) { - match env_var.as_str() { - "x11" => { - // TODO: propagate - #[cfg(x11_platform)] - return EventLoop::new_x11_any_thread() - .expect("Failed to initialize X11 backend"); - #[cfg(not(x11_platform))] - panic!("x11 feature is not enabled") - } - "wayland" => { - #[cfg(wayland_platform)] - return EventLoop::new_wayland_any_thread() - .expect("Failed to initialize Wayland backend"); - #[cfg(not(wayland_platform))] - panic!("wayland feature is not enabled"); - } - _ => panic!( - "Unknown environment variable value for {BACKEND_PREFERENCE_ENV_VAR}, try one of `x11`,`wayland`", - ), - } - } - - #[cfg(wayland_platform)] - let wayland_err = match EventLoop::new_wayland_any_thread() { - Ok(event_loop) => return event_loop, - Err(err) => err, - }; - #[cfg(x11_platform)] - let x11_err = match EventLoop::new_x11_any_thread() { - Ok(event_loop) => return event_loop, - Err(err) => err, - }; + if attributes.forced_backend == Some(Backend::X) || env::var("DISPLAY").is_ok() { + return Ok(EventLoop::new_x11_any_thread().unwrap()); + } - #[cfg(not(wayland_platform))] - let wayland_err = "backend disabled"; - #[cfg(not(x11_platform))] - let x11_err = "backend disabled"; - - panic!( - "Failed to initialize any backend! Wayland status: {wayland_err:?} X11 status: {x11_err:?}", - ); + Err(EventLoopError::Os(os_error!(OsError::Misc( + "neither WAYLAND_DISPLAY nor DISPLAY is set." + )))) } #[cfg(wayland_platform)] - fn new_wayland_any_thread() -> Result, Box> { + fn new_wayland_any_thread() -> Result, EventLoopError> { wayland::EventLoop::new().map(|evlp| EventLoop::Wayland(Box::new(evlp))) } @@ -834,14 +779,14 @@ impl EventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) } - pub fn run(mut self, callback: F) -> Result<(), RunLoopError> + pub fn run(mut self, callback: F) -> Result<(), EventLoopError> where F: FnMut(crate::event::Event, &RootELW, &mut ControlFlow), { self.run_ondemand(callback) } - pub fn run_ondemand(&mut self, callback: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, callback: F) -> Result<(), EventLoopError> where F: FnMut(crate::event::Event, &RootELW, &mut ControlFlow), { diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index f4b8f979..335b1bc2 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -1,7 +1,6 @@ //! The event-loop routines. use std::cell::RefCell; -use std::error::Error; use std::io::Result as IOResult; use std::marker::PhantomData; use std::mem; @@ -13,11 +12,12 @@ use std::time::{Duration, Instant}; use raw_window_handle::{RawDisplayHandle, WaylandDisplayHandle}; use sctk::reexports::calloop; +use sctk::reexports::calloop::Error as CalloopError; use sctk::reexports::client::globals; use sctk::reexports::client::{Connection, Proxy, QueueHandle, WaylandSource}; use crate::dpi::{LogicalSize, PhysicalSize}; -use crate::error::{OsError as RootOsError, RunLoopError}; +use crate::error::{EventLoopError, OsError as RootOsError}; use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; use crate::platform::pump_events::PumpStatus; @@ -33,7 +33,7 @@ use sink::EventSink; use super::state::{WindowCompositorUpdate, WinitState}; use super::window::state::FrameCallbackState; -use super::{DeviceId, WindowId}; +use super::{DeviceId, WaylandError, WindowId}; type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource, WinitState>; @@ -73,22 +73,38 @@ pub struct EventLoop { } impl EventLoop { - pub fn new() -> Result, Box> { - let connection = Connection::connect_to_env()?; + pub fn new() -> Result, EventLoopError> { + macro_rules! map_err { + ($e:expr, $err:expr) => { + $e.map_err(|error| os_error!($err(error).into())) + }; + } - let (globals, mut event_queue) = globals::registry_queue_init(&connection)?; + let connection = map_err!(Connection::connect_to_env(), WaylandError::Connection)?; + + let (globals, mut event_queue) = map_err!( + globals::registry_queue_init(&connection), + WaylandError::Global + )?; let queue_handle = event_queue.handle(); - let event_loop = calloop::EventLoop::::try_new()?; + let event_loop = map_err!( + calloop::EventLoop::::try_new(), + WaylandError::Calloop + )?; - let mut winit_state = WinitState::new(&globals, &queue_handle, event_loop.handle())?; + let mut winit_state = WinitState::new(&globals, &queue_handle, event_loop.handle()) + .map_err(|error| os_error!(error))?; // NOTE: do a roundtrip after binding the globals to prevent potential // races with the server. - event_queue.roundtrip(&mut winit_state)?; + map_err!( + event_queue.roundtrip(&mut winit_state), + WaylandError::Dispatch + )?; // Register Wayland source. - let wayland_source = WaylandSource::new(event_queue)?; + let wayland_source = map_err!(WaylandSource::new(event_queue), WaylandError::Wire)?; let wayland_dispatcher = calloop::Dispatcher::new(wayland_source, |_, queue, winit_state: &mut WinitState| { let result = queue.dispatch_pending(winit_state); @@ -101,34 +117,50 @@ impl EventLoop { result }); - event_loop - .handle() - .register_dispatcher(wayland_dispatcher.clone())?; + map_err!( + event_loop + .handle() + .register_dispatcher(wayland_dispatcher.clone()), + WaylandError::Calloop + )?; // Setup the user proxy. let pending_user_events = Rc::new(RefCell::new(Vec::new())); let pending_user_events_clone = pending_user_events.clone(); let (user_events_sender, user_events_channel) = calloop::channel::channel(); - event_loop.handle().insert_source( - user_events_channel, - move |event, _, winit_state: &mut WinitState| { - if let calloop::channel::Event::Msg(msg) = event { - winit_state.dispatched_events = true; - pending_user_events_clone.borrow_mut().push(msg); - } - }, - )?; + let result = event_loop + .handle() + .insert_source( + user_events_channel, + move |event, _, winit_state: &mut WinitState| { + if let calloop::channel::Event::Msg(msg) = event { + winit_state.dispatched_events = true; + pending_user_events_clone.borrow_mut().push(msg); + } + }, + ) + .map_err(|error| error.error); + map_err!(result, WaylandError::Calloop)?; // An event's loop awakener to wake up for window events from winit's windows. - let (event_loop_awakener, event_loop_awakener_source) = calloop::ping::make_ping()?; - event_loop.handle().insert_source( - event_loop_awakener_source, - move |_, _, winit_state: &mut WinitState| { - // Mark that we have something to dispatch. - winit_state.dispatched_events = true; - }, + let (event_loop_awakener, event_loop_awakener_source) = map_err!( + calloop::ping::make_ping() + .map_err(|error| CalloopError::OtherError(Box::new(error).into())), + WaylandError::Calloop )?; + let result = event_loop + .handle() + .insert_source( + event_loop_awakener_source, + move |_, _, winit_state: &mut WinitState| { + // Mark that we have something to dispatch. + winit_state.dispatched_events = true; + }, + ) + .map_err(|error| error.error); + map_err!(result, WaylandError::Calloop)?; + let window_target = EventLoopWindowTarget { connection: connection.clone(), wayland_dispatcher: wayland_dispatcher.clone(), @@ -158,12 +190,12 @@ impl EventLoop { Ok(event_loop) } - pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { if self.loop_running { - return Err(RunLoopError::AlreadyRunning); + return Err(EventLoopError::AlreadyRunning); } let exit = loop { @@ -172,7 +204,7 @@ impl EventLoop { break Ok(()); } PumpStatus::Exit(code) => { - break Err(RunLoopError::ExitFailure(code)); + break Err(EventLoopError::ExitFailure(code)); } _ => { continue; @@ -184,7 +216,7 @@ impl EventLoop { // `run_ondemand` calls but if they have only just dropped their // windows we need to make sure those last requests are sent to the // compositor. - let _ = self.roundtrip().map_err(RunLoopError::Os); + let _ = self.roundtrip().map_err(EventLoopError::Os); exit } @@ -617,10 +649,10 @@ impl EventLoop { let mut wayland_source = self.wayland_dispatcher.as_source_mut(); let event_queue = wayland_source.queue(); - event_queue.roundtrip(state).map_err(|_| { - os_error!(OsError::WaylandMisc( - "failed to do a final roundtrip before exiting the loop." - )) + event_queue.roundtrip(state).map_err(|error| { + os_error!(OsError::WaylandError(Arc::new(WaylandError::Dispatch( + error + )))) }) } } diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index 36439821..6d232b0d 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -2,10 +2,14 @@ //! Winit's Wayland backend. -use sctk::reexports::client::protocol::wl_surface::WlSurface; -use sctk::reexports::client::Proxy; +use std::fmt::Display; +use std::sync::Arc; -pub use crate::platform_impl::platform::WindowId; +use sctk::reexports::client::globals::{BindError, GlobalError}; +use sctk::reexports::client::protocol::wl_surface::WlSurface; +use sctk::reexports::client::{self, ConnectError, DispatchError, Proxy}; + +pub use crate::platform_impl::platform::{OsError, WindowId}; pub use event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; pub use output::{MonitorHandle, VideoMode}; pub use window::Window; @@ -17,6 +21,46 @@ mod state; mod types; mod window; +#[derive(Debug)] +pub enum WaylandError { + /// Error connecting to the socket. + Connection(ConnectError), + + /// Error binding the global. + Global(GlobalError), + + // Bind error. + Bind(BindError), + + /// Error during the dispatching the event queue. + Dispatch(DispatchError), + + /// Calloop error. + Calloop(calloop::Error), + + /// Wayland + Wire(client::backend::WaylandError), +} + +impl Display for WaylandError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WaylandError::Connection(error) => error.fmt(f), + WaylandError::Global(error) => error.fmt(f), + WaylandError::Bind(error) => error.fmt(f), + WaylandError::Dispatch(error) => error.fmt(f), + WaylandError::Calloop(error) => error.fmt(f), + WaylandError::Wire(error) => error.fmt(f), + } + } +} + +impl From for OsError { + fn from(value: WaylandError) -> Self { + Self::WaylandError(Arc::new(value)) + } +} + /// Dummy device id, since Wayland doesn't have device events. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId; diff --git a/src/platform_impl/linux/wayland/state.rs b/src/platform_impl/linux/wayland/state.rs index 5c9bf9c7..762f97ac 100644 --- a/src/platform_impl/linux/wayland/state.rs +++ b/src/platform_impl/linux/wayland/state.rs @@ -1,5 +1,4 @@ use std::cell::RefCell; -use std::error::Error; use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; @@ -24,6 +23,7 @@ use sctk::shm::{Shm, ShmHandler}; use sctk::subcompositor::SubcompositorState; use crate::dpi::LogicalSize; +use crate::platform_impl::OsError; use super::event_loop::sink::EventSink; use super::output::MonitorHandle; @@ -35,7 +35,7 @@ use super::types::wp_fractional_scaling::FractionalScalingManager; use super::types::wp_viewporter::ViewporterState; use super::types::xdg_activation::XdgActivationState; use super::window::{WindowRequests, WindowState}; -use super::WindowId; +use super::{WaylandError, WindowId}; /// Winit's Wayland state. pub struct WinitState { @@ -116,14 +116,16 @@ impl WinitState { globals: &GlobalList, queue_handle: &QueueHandle, loop_handle: LoopHandle<'static, WinitState>, - ) -> Result> { + ) -> Result { let registry_state = RegistryState::new(globals); - let compositor_state = CompositorState::bind(globals, queue_handle)?; + let compositor_state = + CompositorState::bind(globals, queue_handle).map_err(WaylandError::Bind)?; let subcompositor_state = SubcompositorState::bind( compositor_state.wl_compositor().clone(), globals, queue_handle, - )?; + ) + .map_err(WaylandError::Bind)?; let output_state = OutputState::new(globals, queue_handle); let monitors = output_state.outputs().map(MonitorHandle::new).collect(); @@ -148,9 +150,9 @@ impl WinitState { subcompositor_state: Arc::new(subcompositor_state), output_state, seat_state, - shm: Shm::bind(globals, queue_handle)?, + shm: Shm::bind(globals, queue_handle).map_err(WaylandError::Bind)?, - xdg_shell: XdgShell::bind(globals, queue_handle)?, + xdg_shell: XdgShell::bind(globals, queue_handle).map_err(WaylandError::Bind)?, xdg_activation: XdgActivationState::bind(globals, queue_handle).ok(), windows: Default::default(), diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index a0a51b7b..14085808 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -36,7 +36,7 @@ use super::event_loop::sink::EventSink; use super::output::MonitorHandle; use super::state::WinitState; use super::types::xdg_activation::XdgActivationTokenData; -use super::{EventLoopWindowTarget, WindowId}; +use super::{EventLoopWindowTarget, WaylandError, WindowId}; pub(crate) mod state; @@ -205,18 +205,18 @@ impl Window { let event_queue = wayland_source.queue(); // Do a roundtrip. - event_queue.roundtrip(&mut state).map_err(|_| { - os_error!(OsError::WaylandMisc( - "failed to do initial roundtrip for the window." - )) + event_queue.roundtrip(&mut state).map_err(|error| { + os_error!(OsError::WaylandError(Arc::new(WaylandError::Dispatch( + error + )))) })?; // XXX Wait for the initial configure to arrive. while !window_state.lock().unwrap().is_configured() { - event_queue.blocking_dispatch(&mut state).map_err(|_| { - os_error!(OsError::WaylandMisc( - "failed to dispatch queue while waiting for initial configure." - )) + event_queue.blocking_dispatch(&mut state).map_err(|error| { + os_error!(OsError::WaylandError(Arc::new(WaylandError::Dispatch( + error + )))) })?; } @@ -574,9 +574,7 @@ impl Window { Ok(()) } else { let region = Region::new(&*self.compositor).map_err(|_| { - ExternalError::Os(os_error!(OsError::WaylandMisc( - "failed to set input region." - ))) + ExternalError::Os(os_error!(OsError::Misc("failed to set input region."))) })?; region.add(0, 0, 0, 0); surface.set_input_region(Some(region.wl_region())); diff --git a/src/platform_impl/linux/wayland/window/state.rs b/src/platform_impl/linux/wayland/window/state.rs index e0c49202..abe88879 100644 --- a/src/platform_impl/linux/wayland/window/state.rs +++ b/src/platform_impl/linux/wayland/window/state.rs @@ -712,7 +712,7 @@ impl WindowState { // Positon can be set only for locked cursor. if self.cursor_grab_mode.current_grab_mode != CursorGrabMode::Locked { return Err(ExternalError::Os(os_error!( - crate::platform_impl::OsError::WaylandMisc( + crate::platform_impl::OsError::Misc( "cursor position can be set only for locked cursor." ) ))); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 0746c42d..787f3994 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -64,7 +64,7 @@ use self::{ }; use super::{common::xkb_state::KbdState, OsError}; use crate::{ - error::{OsError as RootOsError, RunLoopError}, + error::{EventLoopError, OsError as RootOsError}, event::{Event, StartCause}, event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform::pump_events::PumpStatus, @@ -432,12 +432,12 @@ impl EventLoop { &self.target } - pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootELW, &mut ControlFlow), { if self.loop_running { - return Err(RunLoopError::AlreadyRunning); + return Err(EventLoopError::AlreadyRunning); } let exit = loop { @@ -446,7 +446,7 @@ impl EventLoop { break Ok(()); } PumpStatus::Exit(code) => { - break Err(RunLoopError::ExitFailure(code)); + break Err(EventLoopError::ExitFailure(code)); } _ => { continue; @@ -460,7 +460,7 @@ impl EventLoop { // X Server. let wt = get_xtarget(&self.target); wt.x_connection().sync_with_server().map_err(|x_err| { - RunLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err))))) + EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err))))) })?; exit diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 1e24a06a..65e51eb1 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -507,7 +507,7 @@ impl UnownedWindow { &mut supported_ptr, ); if supported_ptr == ffi::False { - return Err(os_error!(OsError::XMisc( + return Err(os_error!(OsError::Misc( "`XkbSetDetectableAutoRepeat` failed" ))); } @@ -1525,7 +1525,7 @@ impl UnownedWindow { } _ => unreachable!(), } - .map_err(|err| ExternalError::Os(os_error!(OsError::XMisc(err)))) + .map_err(|err| ExternalError::Os(os_error!(OsError::Misc(err)))) } CursorGrabMode::Locked => { return Err(ExternalError::NotSupported(NotSupportedError::new())); diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 9d8b4782..f4f2ea49 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -24,7 +24,7 @@ use raw_window_handle::{AppKitDisplayHandle, RawDisplayHandle}; use super::appkit::{NSApp, NSApplicationActivationPolicy, NSEvent, NSWindow}; use crate::{ - error::RunLoopError, + error::EventLoopError, event::Event, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget}, platform::{macos::ActivationPolicy, pump_events::PumpStatus}, @@ -148,7 +148,9 @@ impl Default for PlatformSpecificEventLoopAttributes { } impl EventLoop { - pub(crate) fn new(attributes: &PlatformSpecificEventLoopAttributes) -> Self { + pub(crate) fn new( + attributes: &PlatformSpecificEventLoopAttributes, + ) -> Result { if !is_main_thread() { panic!("On macOS, `EventLoop` must be created on the main thread!"); } @@ -178,7 +180,7 @@ impl EventLoop { let panic_info: Rc = Default::default(); setup_control_flow_observers(Rc::downgrade(&panic_info)); - EventLoop { + Ok(EventLoop { _delegate: delegate, window_target: Rc::new(RootWindowTarget { p: Default::default(), @@ -186,14 +188,14 @@ impl EventLoop { }), panic_info, _callback: None, - } + }) } pub fn window_target(&self) -> &RootWindowTarget { &self.window_target } - pub fn run(mut self, callback: F) -> Result<(), RunLoopError> + pub fn run(mut self, callback: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootWindowTarget, &mut ControlFlow), { @@ -204,12 +206,12 @@ impl EventLoop { // `pump_events` elegantly (we just ask to run the loop for a "short" amount of // time and so a layered implementation would end up using a lot of CPU due to // redundant wake ups. - pub fn run_ondemand(&mut self, callback: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, callback: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootWindowTarget, &mut ControlFlow), { if AppState::is_running() { - return Err(RunLoopError::AlreadyRunning); + return Err(EventLoopError::AlreadyRunning); } // # Safety @@ -287,7 +289,7 @@ impl EventLoop { if exit_code == 0 { Ok(()) } else { - Err(RunLoopError::ExitFailure(exit_code)) + Err(EventLoopError::ExitFailure(exit_code)) } } diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 71d733d9..5ffe3864 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -12,7 +12,7 @@ use orbclient::{ use raw_window_handle::{OrbitalDisplayHandle, RawDisplayHandle}; use crate::{ - error::RunLoopError, + error::EventLoopError, event::{self, Ime, Modifiers, StartCause}, event_loop::{self, ControlFlow}, keyboard::{ @@ -22,8 +22,8 @@ use crate::{ }; use super::{ - DeviceId, KeyEventExtra, MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket, - TimeSocket, WindowId, WindowProperties, + DeviceId, KeyEventExtra, MonitorHandle, OsError, PlatformSpecificEventLoopAttributes, + RedoxSocket, TimeSocket, WindowId, WindowProperties, }; fn convert_scancode(scancode: u8) -> KeyCode { @@ -270,12 +270,20 @@ pub struct EventLoop { } impl EventLoop { - pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Self { + pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { let (user_events_sender, user_events_receiver) = mpsc::channel(); - let event_socket = Arc::new(RedoxSocket::event().unwrap()); + let event_socket = Arc::new( + RedoxSocket::event() + .map_err(OsError::new) + .map_err(|error| EventLoopError::Os(os_error!(error)))?, + ); - let wake_socket = Arc::new(TimeSocket::open().unwrap()); + let wake_socket = Arc::new( + TimeSocket::open() + .map_err(OsError::new) + .map_err(|error| EventLoopError::Os(os_error!(error)))?, + ); event_socket .write(&syscall::Event { @@ -283,9 +291,10 @@ impl EventLoop { flags: syscall::EventFlags::EVENT_READ, data: wake_socket.0.fd, }) - .unwrap(); + .map_err(OsError::new) + .map_err(|error| EventLoopError::Os(os_error!(error)))?; - Self { + Ok(Self { windows: Vec::new(), window_target: event_loop::EventLoopWindowTarget { p: EventLoopWindowTarget { @@ -299,7 +308,7 @@ impl EventLoop { }, _marker: std::marker::PhantomData, }, - } + }) } fn process_event( @@ -443,7 +452,7 @@ impl EventLoop { } } - pub fn run(mut self, mut event_handler_inner: F) -> Result<(), RunLoopError> + pub fn run(mut self, mut event_handler_inner: F) -> Result<(), EventLoopError> where F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { @@ -685,7 +694,7 @@ impl EventLoop { if code == 0 { Ok(()) } else { - Err(RunLoopError::ExitFailure(code)) + Err(EventLoopError::ExitFailure(code)) } } diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 961f6c4e..5aa56328 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -1,6 +1,8 @@ #![cfg(target_os = "redox")] +use std::fmt::{self, Display, Formatter}; use std::str; +use std::sync::Arc; use crate::dpi::{PhysicalPosition, PhysicalSize}; @@ -176,13 +178,18 @@ impl<'a> fmt::Display for WindowProperties<'a> { } } -#[derive(Default, Clone, Debug)] -pub struct OsError; +#[derive(Clone, Debug)] +pub struct OsError(Arc); + +impl OsError { + fn new(error: syscall::Error) -> Self { + Self(Arc::new(error)) + } +} -use std::fmt::{self, Display, Formatter}; impl Display for OsError { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { - write!(fmt, "Redox OS Error") + self.0.fmt(fmt) } } diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 60c9a086..48c95fc2 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -1,16 +1,18 @@ +use std::marker::PhantomData; + +use crate::error::EventLoopError; +use crate::event::Event; +use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; + +use super::{backend, device, window}; + mod proxy; pub(crate) mod runner; mod state; mod window_target; -pub use self::proxy::EventLoopProxy; -pub use self::window_target::EventLoopWindowTarget; - -use super::{backend, device, window}; -use crate::event::Event; -use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; - -use std::marker::PhantomData; +pub use proxy::EventLoopProxy; +pub use window_target::EventLoopWindowTarget; pub struct EventLoop { elw: RootEventLoopWindowTarget, @@ -20,13 +22,13 @@ pub struct EventLoop { pub(crate) struct PlatformSpecificEventLoopAttributes {} impl EventLoop { - pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Self { - EventLoop { + pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { + Ok(EventLoop { elw: RootEventLoopWindowTarget { p: EventLoopWindowTarget::new(), _marker: PhantomData, }, - } + }) } pub fn run(self, mut event_handler: F) -> ! diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 7f6c1888..791c64b4 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -75,7 +75,7 @@ use windows_sys::Win32::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize}, - error::RunLoopError, + error::EventLoopError, event::{ DeviceEvent, Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, WindowEvent, @@ -201,7 +201,9 @@ pub struct EventLoopWindowTarget { } impl EventLoop { - pub(crate) fn new(attributes: &mut PlatformSpecificEventLoopAttributes) -> Self { + pub(crate) fn new( + attributes: &mut PlatformSpecificEventLoopAttributes, + ) -> Result { let thread_id = unsafe { GetCurrentThreadId() }; if !attributes.any_thread && thread_id != main_thread_id() { @@ -228,7 +230,7 @@ impl EventLoop { Default::default(), ); - EventLoop { + Ok(EventLoop { thread_msg_sender, window_target: RootELW { p: EventLoopWindowTarget { @@ -239,28 +241,28 @@ impl EventLoop { _marker: PhantomData, }, msg_hook: attributes.msg_hook.take(), - } + }) } pub fn window_target(&self) -> &RootELW { &self.window_target } - pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> + pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootELW, &mut ControlFlow), { self.run_ondemand(event_handler) } - pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> + pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where F: FnMut(Event, &RootELW, &mut ControlFlow), { { let runner = &self.window_target.p.runner_shared; if runner.state() != RunnerState::Uninitialized { - return Err(RunLoopError::AlreadyRunning); + return Err(EventLoopError::AlreadyRunning); } let event_loop_windows_ref = &self.window_target; @@ -295,7 +297,7 @@ impl EventLoop { if exit_code == 0 { Ok(()) } else { - Err(RunLoopError::ExitFailure(exit_code)) + Err(EventLoopError::ExitFailure(exit_code)) } } diff --git a/src/window.rs b/src/window.rs index be515a95..c03eb0f5 100644 --- a/src/window.rs +++ b/src/window.rs @@ -29,7 +29,7 @@ pub use cursor_icon::{CursorIcon, ParseError as CursorIconParseError}; /// window::Window, /// }; /// -/// let mut event_loop = EventLoop::new(); +/// let mut event_loop = EventLoop::new().unwrap(); /// let window = Window::new(&event_loop).unwrap(); /// /// event_loop.run(move |event, _, control_flow| { @@ -570,7 +570,7 @@ impl Window { /// ```no_run /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// # fn swap_buffers() {} /// // Do the actual drawing with OpenGL. @@ -660,7 +660,7 @@ impl Window { /// # use winit::dpi::{LogicalPosition, PhysicalPosition}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the position in logical dimensions like this: /// window.set_outer_position(LogicalPosition::new(400.0, 200.0)); @@ -720,7 +720,7 @@ impl Window { /// # use winit::dpi::{LogicalSize, PhysicalSize}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the size in logical dimensions like this: /// let _ = window.request_inner_size(LogicalSize::new(400.0, 200.0)); @@ -763,7 +763,7 @@ impl Window { /// # use winit::dpi::{LogicalSize, PhysicalSize}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the size in logical dimensions like this: /// window.set_min_inner_size(Some(LogicalSize::new(400.0, 200.0))); @@ -786,7 +786,7 @@ impl Window { /// # use winit::dpi::{LogicalSize, PhysicalSize}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the size in logical dimensions like this: /// window.set_max_inner_size(Some(LogicalSize::new(400.0, 200.0))); @@ -1098,7 +1098,7 @@ impl Window { /// # use winit::dpi::{LogicalPosition, PhysicalPosition, LogicalSize, PhysicalSize}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the position in logical dimensions like this: /// window.set_ime_cursor_area(LogicalPosition::new(400.0, 200.0), LogicalSize::new(100, 100)); @@ -1266,7 +1266,7 @@ impl Window { /// # use winit::dpi::{LogicalPosition, PhysicalPosition}; /// # use winit::event_loop::EventLoop; /// # use winit::window::Window; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// // Specify the position in logical dimensions like this: /// window.set_cursor_position(LogicalPosition::new(400.0, 200.0)); @@ -1292,7 +1292,7 @@ impl Window { /// ```no_run /// # use winit::event_loop::EventLoop; /// # use winit::window::{CursorGrabMode, Window}; - /// # let mut event_loop = EventLoop::new(); + /// # let mut event_loop = EventLoop::new().unwrap(); /// # let window = Window::new(&event_loop).unwrap(); /// window.set_cursor_grab(CursorGrabMode::Confined) /// .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked))