summaryrefslogtreecommitdiff
path: root/src/window_manager.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/window_manager.rs')
-rw-r--r--src/window_manager.rs198
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()
- }
-}