diff --git a/Cargo.toml b/Cargo.toml index 34364b3..120984e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ name = "demo_glium" name = "demo_gl" [features] -default = ["image"] +default = ["image", "glium_backend"] glium_backend = ["glium"] gl_backend = ["gl", "glutin", "memoffset"] @@ -37,7 +37,7 @@ gl_backend = ["gl", "glutin", "memoffset"] log = { version = "0.4" } serde = { version = "1", features = [ "derive" ] } rusttype = { version = "0.9" } -winit = "0.27" +winit = "0.30" parking_lot = { version = "0.12" } notify = { version = "4" } rustc-hash = "2" @@ -45,9 +45,9 @@ serde_yaml = "0.8" pulldown-cmark = { version = "0.12", default-features = false } image = { version = "0.25", optional = true, default-features = false, features = [ "png", "jpeg" ] } -glium = { version = "0.32", optional = true } +glium = { version = "0.36", optional = true } futures = { version = "0.3", optional = true } bytemuck = { version = "1", optional = true } gl = { version = "0.14", optional = true} -glutin = { version = "0.29", optional = true} +glutin = { version = "0.32", optional = true} memoffset = { version = "0.9", optional = true} diff --git a/examples/demo_glium.rs b/examples/demo_glium.rs index 087ab59..8f44508 100644 --- a/examples/demo_glium.rs +++ b/examples/demo_glium.rs @@ -1,5 +1,5 @@ -use winit::{event::{Event, WindowEvent}, event_loop::{EventLoop, ControlFlow}}; -use thyme::bench; +use winit::{application::ApplicationHandler, event::WindowEvent}; +use thyme::{bench, Context, ContextBuilder, GliumRenderer, WinitError, WinitIo}; mod demo; @@ -8,71 +8,94 @@ mod demo; /// the `demo.rs` file contains the Thyme UI code and logic. /// A simple party creator and character sheet for an RPG. fn main() -> Result<(), Box> { - use glium::glutin::window::WindowBuilder; - use glium::{Display, Surface}; - // initialize our very basic logger so error messages go to stdout thyme::log::init(log::Level::Warn).unwrap(); let window_size = [1280.0, 720.0]; - let events_loop = EventLoop::new(); + + let event_loop = glium::winit::event_loop::EventLoop::builder() + .build().map_err(|e| thyme::Error::Winit(WinitError::EventLoop(e)))?; // create glium display - let builder = WindowBuilder::new() + let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() .with_title("Thyme Demo") - .with_inner_size(glium::glutin::dpi::LogicalSize::new(window_size[0], window_size[1])); - let context = glium::glutin::ContextBuilder::new(); - let display = Display::new(builder, context, &events_loop)?; + .with_inner_size(window_size[0] as u32, window_size[1] as u32) + .build(&event_loop); // create thyme backend - let mut renderer = thyme::GliumRenderer::new(&display)?; - let mut io = thyme::WinitIo::new(&events_loop, window_size.into())?; - let mut context_builder = thyme::ContextBuilder::with_defaults(); + let mut renderer = GliumRenderer::new(&display)?; + let mut io = WinitIo::new(&window, window_size.into())?; + let mut context_builder = ContextBuilder::with_defaults(); demo::register_assets(&mut context_builder); - let mut context = context_builder.build(&mut renderer, &mut io)?; + let context = context_builder.build(&mut renderer, &mut io)?; - let mut party = demo::Party::default(); + let party = demo::Party::default(); - let mut last_frame = std::time::Instant::now(); - let frame_time = std::time::Duration::from_millis(16); - - // run main loop - events_loop.run(move |event, _, control_flow| match event { - Event::MainEventsCleared => { - if std::time::Instant::now() > last_frame + frame_time { - display.gl_window().window().request_redraw(); - } - *control_flow = ControlFlow::WaitUntil(last_frame + frame_time); - }, - Event::RedrawRequested(_) => { - last_frame = std::time::Instant::now(); + let mut app = AppRunner { io, renderer, context, display, window, party, frames: 0 }; - party.check_context_changes(&mut context, &mut renderer); + let start = std::time::Instant::now(); - let mut target = display.draw(); - target.clear_color(0.21404, 0.21404, 0.21404, 1.0); // manual sRGB conversion for 0.5 + event_loop.run_app(&mut app)?; - bench::run("thyme", || { - display.gl_window().window().set_cursor_visible(!party.theme_has_mouse_cursor()); + let finish = std::time::Instant::now(); - let mut ui = context.create_frame(); + log::warn!("Drew {} frames in {:.2}s", app.frames, (finish - start).as_secs_f32()); - bench::run("frame", || { - demo::build_ui(&mut ui, &mut party); - }); + Ok(()) +} - bench::run("draw", || { - renderer.draw_frame(&mut target, ui).unwrap(); - }); - }); +struct AppRunner { + io: WinitIo, + renderer: GliumRenderer, + context: Context, + display: glium::Display, + window: winit::window::Window, + party: demo::Party, + frames: u32, +} - target.finish().unwrap(); - }, - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, - event => { - io.handle_event(&mut context, &event); +impl ApplicationHandler for AppRunner { + fn resumed(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { } + + fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { + self.window.request_redraw(); + } + + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + _window_id: winit::window::WindowId, + event: WindowEvent, + ) { + use glium::Surface; + match event { + WindowEvent::RedrawRequested => { + let mut target = self.display.draw(); + target.clear_color(0.25, 0.25, 0.25, 1.0); + + bench::run("thyme", || { + self.window.set_cursor_visible(!self.party.theme_has_mouse_cursor()); + + let mut ui = self.context.create_frame(); + + bench::run("frame", || { + demo::build_ui(&mut ui, &mut self.party); + }); + + bench::run("draw", || { + self.renderer.draw_frame(&mut target, ui).unwrap(); + }); + }); + + target.finish().unwrap(); + self.frames += 1; + } + WindowEvent::CloseRequested => event_loop.exit(), + event => { + self.io.handle_event(&mut self.context, &event); + } } - }) -} + } +} \ No newline at end of file diff --git a/examples/hello_gl.rs b/examples/hello_gl.rs index 6580b81..19036ab 100644 --- a/examples/hello_gl.rs +++ b/examples/hello_gl.rs @@ -15,5 +15,7 @@ fn main() -> Result<(), Box> { ui.button("label", "Hello, World!"); }); - }); + })?; + + Ok(()) } \ No newline at end of file diff --git a/examples/hello_glium.rs b/examples/hello_glium.rs index fdca705..0c8ea4d 100644 --- a/examples/hello_glium.rs +++ b/examples/hello_glium.rs @@ -15,5 +15,7 @@ fn main() -> Result<(), Box> { ui.button("label", "Hello, World!"); }); - }); + })?; + + Ok(()) } \ No newline at end of file diff --git a/src/app_builder.rs b/src/app_builder.rs index 0f05269..470f081 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -1,5 +1,8 @@ use std::path::PathBuf; +use glium::glutin::surface::WindowSurface; +use winit::{application::ApplicationHandler, error::EventLoopError}; + use crate::{Error, Point, BuildOptions, ContextBuilder, Context, WinitIo, Frame}; /// An easy to use but still fairly configurable builder, allowing you to get @@ -192,8 +195,13 @@ impl AppBuilder { /// builder and using the [`GlRenderer`](struct.GlRenderer.html). #[cfg(feature="gl_backend")] pub fn build_gl(self) -> Result { - use glutin::event_loop::EventLoop; + use glium::backend::Facade; + use glutin::context::{ContextApi, ContextAttributesBuilder, Version}; + use winit::raw_window_handle::HasWindowHandle; + use glutin::display::GlDisplay; + use crate::gl_backend::GlError; + use crate::winit_io::WinitError; const OPENGL_MAJOR_VERSION: u8 = 3; const OPENGL_MINOR_VERSION: u8 = 2; @@ -202,33 +210,43 @@ impl AppBuilder { crate::log::init(log::Level::Warn).unwrap(); } - let event_loop = EventLoop::new(); - let window_builder = glutin::window::WindowBuilder::new() - .with_title(&self.title) - .with_inner_size(glutin::dpi::LogicalSize::new(self.window_size.x, self.window_size.y)); - - let windowed_context = glutin::ContextBuilder::new() - .with_gl(glutin::GlRequest::Specific( - glutin::Api::OpenGl, - (OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION), - )) - .build_windowed(window_builder, &event_loop) - .map_err(GlError::GlutinCreation) - .map_err(Error::Gl)?; - - let windowed_context = unsafe { - windowed_context - .make_current() - .map_err(|(_context, e)| GlError::GlutinContext(e)) - .map_err(Error::Gl)? - }; - - { - let gl_context = windowed_context.context(); - gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _) - } + let event_loop = glium::winit::event_loop::EventLoop::builder() + .build().map_err(|e| Error::Winit(WinitError::EventLoop(e)))?; - let mut io = crate::WinitIo::new(&event_loop, self.window_size) + let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() + .with_title(&self.title) + .with_inner_size(self.window_size.x as u32, self.window_size.y as u32) + .build(&event_loop); + + let window_handle = window.window_handle().map_err(|e| Error::Winit(WinitError::HandleError(e)))?; + let raw_window_handle = window_handle.as_raw(); + + let context_attrs = ContextAttributesBuilder::new() + .with_context_api(ContextApi::OpenGl(Some(Version::new(OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION)))) + .build(Some(raw_window_handle)); + + // let windowed_context = glutin::ContextBuilder::new() + // .with_gl(glutin::GlRequest::Specific( + // glutin::Api::OpenGl, + // (OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION), + // )) + // .build_windowed(window_builder, &event_loop) + // .map_err(GlError::GlutinCreation) + // .map_err(Error::Gl)?; + + // let windowed_context = unsafe { + // windowed_context + // .make_current() + // .map_err(|(_context, e)| GlError::GlutinContext(e)) + // .map_err(Error::Gl)? + // }; + + // { + // let gl_context = windowed_context.context(); + // gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _) + // } + + let mut io = crate::WinitIo::new(&window, self.window_size) .map_err(Error::Winit)?; let mut renderer = crate::GLRenderer::new(); let mut context_builder = crate::ContextBuilder::new(self.options.clone()); @@ -237,30 +255,28 @@ impl AppBuilder { let context = context_builder.build(&mut renderer, &mut io)?; - Ok(GlApp { io, renderer, context, event_loop, windowed_context }) + Ok(GlApp { io, renderer, context, event_loop, window }) } /// Creates a [`GliumApp`](struct.GliumApp.html) object, setting up Thyme as specified /// in this Builder and using the [`GliumRenderer`](struct.GliumRenderer.html). #[cfg(feature="glium_backend")] pub fn build_glium(self) -> Result { - use glium::glutin::{event_loop::EventLoop, window::WindowBuilder}; - use glium::Display; - use crate::glium_backend::GliumError; + use crate::winit_io::WinitError; if self.logger { crate::log::init(log::Level::Warn).unwrap(); } - let event_loop = EventLoop::new(); - let context = glium::glutin::ContextBuilder::new(); - let builder = WindowBuilder::new() + let event_loop = glium::winit::event_loop::EventLoop::builder() + .build().map_err(|e| Error::Winit(WinitError::EventLoop(e)))?; + + let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() .with_title(&self.title) - .with_inner_size(glium::glutin::dpi::LogicalSize::new(self.window_size.x, self.window_size.y)); - let display = Display::new(builder, context, &event_loop).map_err(GliumError::DisplayCreation) - .map_err(Error::Glium)?; + .with_inner_size(self.window_size.x as u32, self.window_size.y as u32) + .build(&event_loop); - let mut io = crate::WinitIo::new(&event_loop, self.window_size) + let mut io = crate::WinitIo::new(&window, self.window_size) .map_err(Error::Winit)?; let mut renderer = crate::GliumRenderer::new(&display) .map_err(Error::Glium)?; @@ -270,7 +286,7 @@ impl AppBuilder { let context = context_builder.build(&mut renderer, &mut io)?; - Ok(GliumApp { io, renderer, context, display, event_loop }) + Ok(GliumApp { io, renderer, context, display, window, event_loop }) } fn register_resources(&self, context_builder: &mut ContextBuilder) -> Result<(), Error> { @@ -324,41 +340,68 @@ pub struct GlApp { pub event_loop: winit::event_loop::EventLoop<()>, /// The OpenGL / Glutin windowed context - pub windowed_context: glutin::ContextWrapper, + pub window: winit::window::Window, + //pub windowed_context: glutin::ContextWrapper, } #[cfg(feature="gl_backend")] -impl GlApp { - /// Runs the Winit main loop for this app - pub fn main_loop(self, f: F) -> ! { - use glutin::{ - event::{Event, WindowEvent}, - event_loop::ControlFlow, - }; - - let event_loop = self.event_loop; - let windowed_context = self.windowed_context; - let mut context = self.context; - let mut renderer = self.renderer; - let mut io = self.io; +struct GlAppRunner { + io: WinitIo, + renderer: crate::GLRenderer, + context: Context, + window: winit::window::Window, + f: F, +} - event_loop.run(move |event, _, control_flow| match event { - Event::MainEventsCleared => { - renderer.clear_color(0.0, 0.0, 0.0, 1.0); - - let mut ui = context.create_frame(); +#[cfg(feature="gl_backend")] +impl ApplicationHandler for GlAppRunner { + fn resumed(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { } + + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + _window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + use winit::event::WindowEvent; + match event { + WindowEvent::RedrawRequested => { + self.renderer.clear_color(0.0, 0.0, 0.0, 0.0); + + let mut ui = self.context.create_frame(); - (f)(&mut ui); + (self.f)(&mut ui); - renderer.draw_frame(ui); + self.renderer.draw_frame(ui); - windowed_context.swap_buffers().unwrap(); + // Was: + // renderer.clear_color(0.0, 0.0, 0.0, 1.0); + // let mut ui = context.create_frame(); + // (f)(&mut ui); + // renderer.draw_frame(ui); + // windowed_context.swap_buffers().unwrap(); } - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, + WindowEvent::CloseRequested => event_loop.exit(), event => { - io.handle_event(&mut context, &event); + self.io.handle_event(&mut self.context, &event); } - }) + } + } +} + +#[cfg(feature="gl_backend")] +impl GlApp { + /// Runs the Winit main loop for this app + pub fn main_loop(self, f: F) -> Result<(), EventLoopError> { + let mut runner = GlAppRunner { + io: self.io, + renderer: self.renderer, + context: self.context, + window: self.window, + f, + }; + + self.event_loop.run_app(&mut runner) } } @@ -376,8 +419,11 @@ pub struct GliumApp { /// The Thyme Context pub context: Context, + /// The Winit Window + pub window: winit::window::Window, + /// The Glium / Winit Display - pub display: glium::Display, + pub display: glium::Display, /// The Glium / Winit Event loop pub event_loop: winit::event_loop::EventLoop<()>, @@ -386,37 +432,64 @@ pub struct GliumApp { #[cfg(feature="glium_backend")] impl GliumApp { /// Runs the Winit main loop for this app - pub fn main_loop(self, f: F) -> ! { - use glium::glutin::{ - event::{Event, WindowEvent}, - event_loop::ControlFlow, + pub fn main_loop(self, f: F) -> Result<(), EventLoopError> { + let mut runner = GliumAppRunner { + io: self.io, + renderer: self.renderer, + context: self.context, + display: self.display, + window: self.window, + f, }; - use glium::Surface; + + self.event_loop.run_app(&mut runner) + } +} + +#[cfg(feature="glium_backend")] +struct GliumAppRunner { + pub io: WinitIo, + pub renderer: crate::GliumRenderer, + pub context: Context, + pub display: glium::Display, + pub window: winit::window::Window, + pub f: F, +} - let event_loop = self.event_loop; - let display = self.display; - let mut context = self.context; - let mut renderer = self.renderer; - let mut io = self.io; +#[cfg(feature="glium_backend")] +impl ApplicationHandler for GliumAppRunner { + fn resumed(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { } + + fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { + self.window.request_redraw(); + } - event_loop.run(move |event, _, control_flow| match event { - Event::MainEventsCleared => { - let mut target = display.draw(); + fn window_event( + &mut self, + event_loop: &winit::event_loop::ActiveEventLoop, + _window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + use glium::Surface; + use winit::event::WindowEvent; + match event { + WindowEvent::RedrawRequested => { + let mut target = self.display.draw(); target.clear_color(0.0, 0.0, 0.0, 0.0); - let mut ui = context.create_frame(); + let mut ui = self.context.create_frame(); - (f)(&mut ui); + (self.f)(&mut ui); - renderer.draw_frame(&mut target, ui).unwrap(); + self.renderer.draw_frame(&mut target, ui).unwrap(); target.finish().unwrap(); } - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, + WindowEvent::CloseRequested => event_loop.exit(), event => { - io.handle_event(&mut context, &event); + self.io.handle_event(&mut self.context, &event); } - }) + } } } diff --git a/src/gl_backend/mod.rs b/src/gl_backend/mod.rs index f9f1c6c..9d99945 100644 --- a/src/gl_backend/mod.rs +++ b/src/gl_backend/mod.rs @@ -566,19 +566,15 @@ pub(crate) struct GLVertex { /// An error originating from the [`GLRenderer`](struct.GLRenderer.html) #[derive(Debug)] pub enum GlError { - /// An error creating the glutin context - GlutinCreation(glutin::CreationError), - - /// An error using or creating the OpenGL context - GlutinContext(glutin::ContextError), + /// An error originating from glutin + Glutin(glutin::error::Error), } impl std::fmt::Display for GlError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use self::GlError::*; match self { - GlutinCreation(e) => write!(f, "Error creating Glutin context: {}", e), - GlutinContext(e) => write!(f, "Error in OpenGL context: {}", e), + Glutin(e) => write!(f, "Glutin error: {}", e), } } } @@ -587,20 +583,7 @@ impl Error for GlError { fn source(&self) -> Option<&(dyn Error + 'static)> { use self::GlError::*; match self { - GlutinCreation(e) => Some(e), - GlutinContext(e) => Some(e), + Glutin(e) => Some(e), } } -} - -impl From for GlError { - fn from(e: glutin::CreationError) -> GlError { - GlError::GlutinCreation(e) - } -} - -impl From for GlError { - fn from(e: glutin::ContextError) -> GlError { - GlError::GlutinContext(e) - } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 37fccc1..932f5b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,7 +435,7 @@ pub use scrollpane::{ScrollpaneBuilder, ShowElement}; pub use theme_definition::{AnimStateKey, AnimState, Align, Color, Layout, WidthRelative, HeightRelative}; pub use window::WindowBuilder; pub use recipes::{InputFieldResult, InputFieldKeyboard}; -pub use winit_io::WinitIo; +pub use winit_io::{WinitIo, WinitError}; pub use render::{IO, Renderer}; diff --git a/src/winit_io/mod.rs b/src/winit_io/mod.rs index 821290d..4f1ab6d 100644 --- a/src/winit_io/mod.rs +++ b/src/winit_io/mod.rs @@ -1,7 +1,8 @@ use std::error::Error; -use winit::event::{ElementState, Event, MouseButton, MouseScrollDelta, VirtualKeyCode, WindowEvent}; -use winit::event_loop::EventLoop; +use winit::event::{ElementState, MouseButton, MouseScrollDelta, WindowEvent}; +use winit::keyboard::{Key, NamedKey, ModifiersKeyState}; +use winit::window::Window; use crate::point::Point; use crate::context::{InputModifiers, Context}; @@ -49,11 +50,11 @@ impl IO for WinitIo { impl WinitIo { /// Creates a new adapter from the given `EventLoop`, with the specified initial display size, /// in logical pixels. This may change over time. - pub fn new( - event_loop: &EventLoop, + pub fn new( + window: &Window, logical_display_size: Point, ) -> Result { - let monitor = event_loop.primary_monitor().ok_or(WinitError::PrimaryMonitorNotFound)?; + let monitor = window.primary_monitor().ok_or(WinitError::PrimaryMonitorNotFound)?; let scale_factor = monitor.scale_factor() as f32; Ok(WinitIo { scale_factor, @@ -62,12 +63,7 @@ impl WinitIo { } /// Handles a winit `Event` and passes it to the Thyme [`Context`](struct.Context.html). - pub fn handle_event(&mut self, context: &mut Context, event: &Event) { - let event = match event { - Event::WindowEvent { event, .. } => event, - _ => return, - }; - + pub fn handle_event(&mut self, context: &mut Context, event: &WindowEvent) { use WindowEvent::*; match event { Resized(size) => { @@ -77,11 +73,11 @@ impl WinitIo { context.set_display_size(size); }, ModifiersChanged(m) => { - context.set_input_modifiers(InputModifiers { - shift: m.shift(), - ctrl: m.ctrl(), - alt: m.alt(), - }); + use ModifiersKeyState::*; + let shift = m.lshift_state() == Pressed || m.rshift_state() == Pressed; + let ctrl = m.lcontrol_state() == Pressed || m.rcontrol_state() == Pressed; + let alt = m.lalt_state() == Pressed || m.ralt_state() == Pressed; + context.set_input_modifiers(InputModifiers { shift, ctrl, alt }); }, WindowEvent::ScaleFactorChanged { scale_factor, .. } => { let scale = *scale_factor as f32; @@ -98,7 +94,9 @@ impl WinitIo { MouseButton::Left => 0, MouseButton::Right => 1, MouseButton::Middle => 2, - MouseButton::Other(index) => *index as usize + 3, + MouseButton::Back => 3, + MouseButton::Forward => 4, + MouseButton::Other(index) => *index as usize + 5, }; context.set_mouse_pressed(pressed, index); @@ -118,14 +116,21 @@ impl WinitIo { CursorMoved { position, .. } => { context.set_mouse_pos((position.x as f32 / self.scale_factor, position.y as f32 / self.scale_factor).into()); }, - ReceivedCharacter(c) => { - context.push_character(*c); - }, - KeyboardInput { input, .. } => { - if let Some(event) = key_event(input.virtual_keycode) { - if let ElementState::Released = input.state { - context.push_key_event(event); - } + KeyboardInput { event, .. } => { + match &event.logical_key { + Key::Named(named_key) => { + if let ElementState::Released = event.state { + if let Some(key) = key_event(*named_key) { + context.push_key_event(key); + } + } + }, + Key::Character(c) => { + for c in c.chars() { + context.push_character(c); + } + }, + Key::Unidentified(_) | Key::Dead(_) => (), } }, _ => (), @@ -133,10 +138,20 @@ impl WinitIo { } } +/// An error of several types originating from winit Windowing functions #[derive(Debug)] pub enum WinitError { + /// No primary monitor is found PrimaryMonitorNotFound, + + /// Internal OS error forwarded to winit Os(winit::error::OsError), + + /// An error in the creation or execution of the EventLoop + EventLoop(winit::error::EventLoopError), + + /// An error getting the window handle associated with a window + HandleError(winit::raw_window_handle::HandleError), } impl std::fmt::Display for WinitError { @@ -145,6 +160,8 @@ impl std::fmt::Display for WinitError { match self { PrimaryMonitorNotFound => write!(f, "Primary monitor not found."), Os(e) => write!(f, "OS Error: {}", e), + EventLoop(e) => write!(f, "Event Loop error: {}", e), + HandleError(e) => write!(f, "Window handle error: {}", e), } } } @@ -155,17 +172,14 @@ impl Error for WinitError { match self { PrimaryMonitorNotFound => None, Os(e) => Some(e), + EventLoop(e) => Some(e), + HandleError(e) => Some(e), } } } -fn key_event(input: Option) -> Option { - let input = match input { - None => return None, - Some(i) => i, - }; - - use VirtualKeyCode::*; +fn key_event(input: NamedKey) -> Option { + use NamedKey::*; Some(match input { Insert => KeyEvent::Insert, Home => KeyEvent::Home, @@ -173,12 +187,12 @@ fn key_event(input: Option) -> Option { End => KeyEvent::End, PageDown => KeyEvent::PageDown, PageUp => KeyEvent::PageUp, - Left => KeyEvent::Left, - Up => KeyEvent::Up, - Right => KeyEvent::Right, - Down => KeyEvent::Down, - Back => KeyEvent::Back, - Return => KeyEvent::Return, + ArrowLeft => KeyEvent::Left, + ArrowUp => KeyEvent::Up, + ArrowRight => KeyEvent::Right, + ArrowDown => KeyEvent::Down, + Backspace => KeyEvent::Back, + Enter => KeyEvent::Return, Space => KeyEvent::Space, Escape => KeyEvent::Escape, Tab => KeyEvent::Tab,