diff --git a/Cargo.toml b/Cargo.toml index f775a10..4693a9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,13 +22,17 @@ circle-ci = { repository = "embedded-graphics/simulator", branch = "master" } [dependencies] image = "0.23.0" base64 = "0.13.0" -embedded-graphics = "0.7.1" +embedded-graphics = "0.8" [dependencies.sdl2] -version = "0.32.2" +version = "0.35.1" +optional = true + +[dependencies.once_cell] +version = "1.8.0" optional = true [features] default = [ "with-sdl" ] fixed_point = [ "embedded-graphics/fixed_point" ] -with-sdl = [ "sdl2" ] +with-sdl = [ "sdl2", "once_cell" ] diff --git a/src/window.rs b/src/window.rs index 9df01a4..4f793a1 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,7 +1,7 @@ use std::{fs::File, io::BufReader, ops::Deref}; #[cfg(feature = "with-sdl")] -use std::{thread, time::Duration}; +use std::{cell::RefCell, thread, time::Duration}; #[cfg(feature = "with-sdl")] use sdl2::{ @@ -11,6 +11,26 @@ use sdl2::{ render, }; +#[cfg(feature = "with-sdl")] +use once_cell::sync::Lazy; + +#[cfg(feature = "with-sdl")] +struct SdlContext { + video_subsystem: sdl2::VideoSubsystem, + event_pump: sdl2::EventPump, +} + +#[cfg(feature = "with-sdl")] +thread_local! { + static SDL: Lazy> = Lazy::new(|| { + let sdl_context = sdl2::init().unwrap(); + RefCell::new(SdlContext { + video_subsystem: sdl_context.video().unwrap(), + event_pump: sdl_context.event_pump().unwrap(), + }) + }); +} + use embedded_graphics::{pixelcolor::Rgb888, prelude::*}; use crate::{ @@ -216,7 +236,6 @@ impl Window { #[cfg(feature = "with-sdl")] struct SdlWindow { canvas: render::Canvas, - event_pump: sdl2::EventPump, } #[cfg(feature = "with-sdl")] @@ -229,21 +248,20 @@ impl SdlWindow { where C: PixelColor + Into, { - let sdl_context = sdl2::init().unwrap(); - let video_subsystem = sdl_context.video().unwrap(); - let size = output_settings.framebuffer_size(display); - let window = video_subsystem - .window(title, size.width, size.height) - .position_centered() - .build() - .unwrap(); + let window = SDL.with(|sdl| { + sdl.borrow_mut() + .video_subsystem + .window(title, size.width, size.height) + .position_centered() + .build() + .unwrap() + }); let canvas = window.into_canvas().build().unwrap(); - let event_pump = sdl_context.event_pump().unwrap(); - Self { canvas, event_pump } + Self { canvas } } pub fn update(&mut self, framebuffer: &OutputImage) { @@ -269,69 +287,83 @@ impl SdlWindow { output_settings: &OutputSettings, ) -> impl Iterator + '_ { let output_settings = output_settings.clone(); - self.event_pump - .poll_iter() - .filter_map(move |event| match event { - Event::Quit { .. } - | Event::KeyDown { - keycode: Some(Keycode::Escape), - .. - } => Some(SimulatorEvent::Quit), - Event::KeyDown { - keycode, - keymod, - repeat, - .. - } => { - if let Some(valid_keycode) = keycode { - Some(SimulatorEvent::KeyDown { - keycode: valid_keycode, - keymod, - repeat, - }) - } else { - None - } + SDL.with(|sdl| { + sdl.borrow_mut() + .event_pump + .poll_iter() + .collect::>() + }) + .into_iter() + .filter_map(move |event| match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => Some(SimulatorEvent::Quit), + Event::KeyDown { + keycode, + keymod, + repeat, + .. + } => { + if let Some(valid_keycode) = keycode { + Some(SimulatorEvent::KeyDown { + keycode: valid_keycode, + keymod, + repeat, + }) + } else { + None } - Event::KeyUp { - keycode, - keymod, - repeat, - .. - } => { - if let Some(valid_keycode) = keycode { - Some(SimulatorEvent::KeyUp { - keycode: valid_keycode, - keymod, - repeat, - }) - } else { - None - } - } - Event::MouseButtonUp { - x, y, mouse_btn, .. - } => { - let point = output_settings.output_to_display(Point::new(x, y)); - Some(SimulatorEvent::MouseButtonUp { point, mouse_btn }) + } + Event::KeyUp { + keycode, + keymod, + repeat, + .. + } => { + if let Some(valid_keycode) = keycode { + Some(SimulatorEvent::KeyUp { + keycode: valid_keycode, + keymod, + repeat, + }) + } else { + None } - Event::MouseButtonDown { - x, y, mouse_btn, .. - } => { - let point = output_settings.output_to_display(Point::new(x, y)); - Some(SimulatorEvent::MouseButtonDown { point, mouse_btn }) + } + Event::MouseButtonUp { + x, y, mouse_btn, .. + } if event.get_window_id() == Some(self.canvas.window().id()) => { + match event.get_window_id() { + Some(id) if id == self.canvas.window().id() => { + let point = output_settings.output_to_display(Point::new(x, y)); + Some(SimulatorEvent::MouseButtonUp { point, mouse_btn }) + } + _ => None, } - Event::MouseWheel { - x, y, direction, .. - } => Some(SimulatorEvent::MouseWheel { + } + Event::MouseButtonDown { + x, y, mouse_btn, .. + } if event.get_window_id() == Some(self.canvas.window().id()) => { + let point = output_settings.output_to_display(Point::new(x, y)); + Some(SimulatorEvent::MouseButtonDown { point, mouse_btn }) + } + Event::MouseWheel { + x, y, direction, .. + } if event.get_window_id() == Some(self.canvas.window().id()) => { + Some(SimulatorEvent::MouseWheel { scroll_delta: Point::new(x, y), direction, - }), - Event::MouseMotion { x, y, .. } => { - let point = output_settings.output_to_display(Point::new(x, y)); - Some(SimulatorEvent::MouseMove { point }) - } - _ => None, - }) + }) + } + Event::MouseMotion { x, y, .. } + if event.get_window_id() == Some(self.canvas.window().id()) => + { + let point = output_settings.output_to_display(Point::new(x, y)); + Some(SimulatorEvent::MouseMove { point }) + } + _ => None, + }) } }