diff options
Diffstat (limited to 'src/window_manager.rs')
-rw-r--r-- | src/window_manager.rs | 198 |
1 files changed, 88 insertions, 110 deletions
diff --git a/src/window_manager.rs b/src/window_manager.rs index 144f1c3..065d517 100644 --- a/src/window_manager.rs +++ b/src/window_manager.rs @@ -1,156 +1,134 @@ use crate::*; -use nosferatu::*; - use std::collections::HashMap; -use winit::event::{Event, MouseButton, StartCause, WindowEvent, MouseScrollDelta}; -use winit::event_loop::EventLoop; -use winit::window::WindowId; - -/// Controls the entire program. -pub struct WindowManager<P: ProgramController> { - limiter: Option<FrameRateLimiter>, - frame_timer: FrameTimer, +use std::time::Duration; +use winit::{event::*, event_loop::{EventLoop, ControlFlow}, window::WindowId}; + +pub struct WindowManager { event_loop: EventLoop<()>, windows: HashMap<WindowId, Window>, - program: P, + min_frame_duration: Duration, } -impl WindowManager<DefaultProgramController> { - pub fn without_program() -> Self { - Self::with_program(DefaultProgramController {}) - } -} - -impl<P: 'static + ProgramController> WindowManager<P> { - pub fn with_program(program: P) -> Self { +impl WindowManager { + pub fn new(min_frame_duration: Duration) -> Self { Self { - limiter: None, - frame_timer: FrameTimer::one_second(), event_loop: EventLoop::new(), windows: HashMap::new(), - program, + min_frame_duration, } } - pub fn with_frame_limit(mut self, limit: usize) -> Self { - self.limiter = Some(FrameRateLimiter::from_frame_rate(limit)); self - } - - /// Used to create one or more windows before the event loop starts. - pub fn create_window(&mut self, controller: Box<dyn WindowController>) { - let window = unsafe { Window::new(&self.event_loop, controller) }; + /// Add a window to the window manager before the event loop begins. + pub fn add_window(&mut self, controller: Box<dyn WindowController>) { + let window = Window::new(&self.event_loop, controller); self.windows.insert(window.id(), window); } - /// Starts the event loop, causing program control to be passed permanently to the window manager. + /// Start the event loop, passing program control to the window manager. pub fn run(mut self) -> ! { - self.event_loop.run(move |event, window_target, control_flow| { - control_flow.set_poll(); - + self.event_loop.run(move |event, _window_target, control_flow| { match event { - // Event loop has just initialised (is only ever emitted once) - Event::NewEvents(StartCause::Init) => self.program.initialise(), + // Called when the event loop is first initialized. + Event::NewEvents(StartCause::Init) => (), + + Event::NewEvents(_) => { + control_flow.set_wait_timeout(self.min_frame_duration); + } + + // Called when an application suspends on a mobile platform. + Event::Suspended => (), + + // Called when an application resumes, or after initialization on non-mobile platforms. + Event::Resumed => (), Event::WindowEvent { window_id, event } => { if let Some(window) = self.windows.get_mut(&window_id) { use WindowEvent::*; + match event { - Resized(dim) => window.resize_buffer(Dimensions::new(dim.width, dim.height)), - Moved(p) => window.controller.on_move(Point::new(p.x, p.y)), - Focused(state) => window.controller.on_focus_change(state), - - CursorEntered { .. } => window.controller.on_mouse_enter(), - CursorLeft { .. } => window.controller.on_mouse_exit(), - CursorMoved { position, .. } => { - let point = Point::new(position.x as i32, position.y as i32); - window.move_mouse(point); - } - MouseWheel {delta, ..} => { - match delta { - MouseScrollDelta::LineDelta(x, y) => { - let (x, y) = (x as f64, y as f64); - if x != 0.0 {window.controller.on_line_scroll_horizontal(x)} - if y != 0.0 {window.controller.on_line_scroll_vertical(y)} - } - MouseScrollDelta::PixelDelta(point) => { - let (x, y) = (point.x, point.y); - if x != 0.0 {window.controller.on_pixel_scroll_horizontal(x)} - if y != 0.0 {window.controller.on_pixel_scroll_vertical(y)} - } + Resized(dim) => window.resize(Dimensions::new(dim.width, dim.height)), + Moved(position) => window.controller.on_move(Point::new(position.x, position.y)), + Focused(is_focused) => window.controller.on_focus_change(is_focused), + + CursorEntered { .. } => window.controller.on_cursor_enter(), + CursorLeft { .. } => window.controller.on_cursor_exit(), + CursorMoved { position: p, .. } => { window.move_cursor(Point::new(p.x as i32, p.y as i32)) } + + MouseWheel {delta, ..} => match delta { + MouseScrollDelta::LineDelta(x, y) => { + let (x, y) = (x as f64, y as f64); + if x != 0.0 {window.controller.on_line_scroll_horizontal(x)} + if y != 0.0 {window.controller.on_line_scroll_vertical(y)} } - }, - MouseInput { state, button, .. } => { - match button { - MouseButton::Left => window.controller.on_left_mouse_button(state.into()), - MouseButton::Middle => window.controller.on_middle_mouse_button(state.into()), - MouseButton::Right => window.controller.on_right_mouse_button(state.into()), - _ => (), + MouseScrollDelta::PixelDelta(point) => { + let (x, y) = (point.x, point.y); + if x != 0.0 {window.controller.on_pixel_scroll_horizontal(x)} + if y != 0.0 {window.controller.on_pixel_scroll_vertical(y)} } - window.bump_mouse(); - + } + MouseInput { state, button, .. } => match button { + MouseButton::Left => window.controller.on_left_mouse_button(state.into()), + MouseButton::Middle => window.controller.on_middle_mouse_button(state.into()), + MouseButton::Right => window.controller.on_right_mouse_button(state.into()), + MouseButton::Other(_) => (), } - KeyboardInput { input, .. } => window.controller.on_keyboard_input(input.into()), + KeyboardInput { input, .. } => if let Ok(input) = input.try_into() { window.controller.on_keyboard_input(input)}, ModifiersChanged(state) => window.controller.on_keyboard_modifier_change(state), - ReceivedCharacter(c) => window.controller.on_character_received(c), - HoveredFile(path) => window.controller.on_file_hovered(path), - DroppedFile(path) => window.controller.on_file_dropped(path), - - // Tell the window, and let it raise its own event to close itself - // When all windows are closed: control_flow.set_exit_with_code(0); - CloseRequested => todo!("window.controller.on_close_requested()"), - _ => (), + ReceivedCharacter(character) => window.controller.on_character_input(character), + HoveredFile(path) => window.controller.on_file_hover(path), + HoveredFileCancelled => window.controller.on_file_hover_cancel(), + DroppedFile(path) => window.controller.on_file_drop(path), + + CloseRequested => { + window.controller.on_close_request(); + *control_flow = ControlFlow::Exit; + }, + Destroyed => window.controller.on_close(), + + Ime(_) => (), + AxisMotion { .. } => (), + Touch(_) => (), + TouchpadRotate { .. } => (), + TouchpadPressure { .. } => (), + TouchpadMagnify { .. } => (), + SmartMagnify { .. } => (), + ScaleFactorChanged { .. } => (), + ThemeChanged(_) => (), + Occluded(_) => (), } } } - // Called each loop before any rendering would begin. + // Called before any render events are called. Event::MainEventsCleared => { - self.frame_timer.tick(); - // println!("{}", self.frame_timer.frame_rate()); - - self.program.on_process(&mut |controller: Box<dyn WindowController>| { - let window = unsafe { Window::new(window_target, controller) }; - self.windows.insert(window.id(), window); - }); for window in self.windows.values_mut() { window.controller.on_process(); - let cursor_icon = window.controller.cursor_icon(); - window.set_cursor_icon(cursor_icon); - // let resizable = window.controller.resizable(); - // window.set_resizable(resizable); - // let cursor_visible = window.controller.cursor_visible(); - // window.set_cursor_visible(cursor_visible); - window.check_render_request(); - let title = window.controller.title(); - window.set_title(&title); - let minimum_dimensions = window.controller.minimum_dimensions(); - window.set_minimum_dimensions(minimum_dimensions); - let maximum_dimensions = window.controller.maximum_dimensions(); - window.set_maximum_dimensions(maximum_dimensions); + window.update_title(); + window.update_minimum_size(); + window.update_maximum_size(); + window.update_resizable(); + window.update_cursor_icon(); + window.update_cursor_visible(); + window.handle_render_request(); } } - // Called if a render was requested for a window + + // Called if a window has requested to be rendered. Event::RedrawRequested(window_id) => { if let Some(window) = self.windows.get_mut(&window_id) { window.render(); } } - // Called after rendering has completed - Event::RedrawEventsCleared => { - if let Some(limiter) = &mut self.limiter { - limiter.tick(); - } - } - _other => {} // todo!("{:?}", other), + // Called after all rendering has completed, or if there were no render requests. + Event::RedrawEventsCleared => (), + + // Called before the program closes. + Event::LoopDestroyed => (), + + _ => (), } }) } } - -impl Default for WindowManager<DefaultProgramController> { - fn default() -> Self { - Self::without_program() - } -} |