summaryrefslogtreecommitdiff
path: root/src/window.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.rs')
-rw-r--r--src/window.rs177
1 files changed, 87 insertions, 90 deletions
diff --git a/src/window.rs b/src/window.rs
index 45e37c9..ffe35e8 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -1,136 +1,133 @@
-mod x11;
use crate::*;
-use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
+
+use std::num::NonZeroU32;
use winit::dpi::{Size, PhysicalSize};
use winit::event_loop::EventLoopWindowTarget;
-use winit::window::{WindowId, Window as WinitWindow, WindowBuilder as WinitWindowBuilder};
-// use raw_gl_context::{GlConfig, GlContext};
+use winit::window::WindowId;
pub struct Window {
pub controller: Box<dyn WindowController>,
- cursor_position: Option<Point>,
- winit_window: WinitWindow,
+ window: winit::window::Window,
buffer: Buffer,
dimensions: Dimensions,
- /// The most recent render request for this window.
- render_hint: RenderHint,
- graphics_context: Box<dyn GraphicsContext>,
- // gl_context: GlContext,
+ #[allow(dead_code)] context: softbuffer::Context,
+ surface: softbuffer::Surface,
+ current_render_hint: RenderHint,
+ previous_cursor_position: Option<Point>,
}
impl Window {
- pub unsafe fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self {
- let mut builder = WinitWindowBuilder::new();
- builder = builder.with_resizable(controller.resizable());
- builder = builder.with_inner_size({
- let dim = controller.initial_dimensions();
- Size::Physical(PhysicalSize::new(dim.width, dim.height))
- });
- if let Some(dim) = controller.minimum_dimensions() {
- let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height });
- builder = builder.with_min_inner_size(size);
- }
- if let Some(dim) = controller.maximum_dimensions() {
- let size = Size::Physical(PhysicalSize { width: dim.width, height: dim.height });
- builder = builder.with_max_inner_size(size);
- }
- let winit_window = builder.build(event_loop).unwrap();
+ pub fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box<dyn WindowController>) -> Self {
+ let window = winit::window::WindowBuilder::new()
+ .with_title(controller.title())
+ .with_resizable(controller.is_resizable())
+ .with_inner_size(dim_to_size(controller.initial_size()))
+ .build(event_loop)
+ .unwrap();
+
+ let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
+ let surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
- let graphics_context: Box<dyn GraphicsContext> = match winit_window.raw_window_handle() {
- RawWindowHandle::Xlib(xlib_handle) => Box::new(x11::X11GraphicsContext::new(xlib_handle)),
- _ => panic!("Unknown window handle type"),
- };
- // let gl_context = GlContext::create(&winit_window, GlConfig::default()).unwrap();
- // gl_context.make_current();
- // gl::load_with(|symbol| {
- // println!("Loaded '{}'", symbol);
- // gl_context.get_proc_address(symbol) as *const _
- // });
Self {
- winit_window,
controller,
- graphics_context,
- render_hint: RenderHint::Redraw,
- // gl_context,
+ window,
buffer: Buffer::new(Dimensions::ZERO),
dimensions: Dimensions::ZERO,
- cursor_position: None,
+ context,
+ surface,
+ previous_cursor_position: None,
+ current_render_hint: RenderHint::Redraw,
}
}
pub fn id(&self) -> WindowId {
- self.winit_window.id()
+ self.window.id()
}
- pub fn set_minimum_dimensions(&mut self, dimensions: Option<Dimensions>) {
- self.winit_window.set_min_inner_size(dimensions.map(|dim| {
- Size::Physical(PhysicalSize { width:dim.width, height:dim.height })
- }))
+ pub fn update_title(&mut self) {
+ self.window.set_title(&self.controller.title());
}
- pub fn set_maximum_dimensions(&mut self, dimensions: Option<Dimensions>) {
- self.winit_window.set_max_inner_size(dimensions.map(|dim| {
- Size::Physical(PhysicalSize { width:dim.width, height:dim.height })
- }))
+
+ pub fn update_cursor_icon(&mut self) {
+ let icon = self.controller.cursor_icon().unwrap_or(CursorIcon::Default);
+ self.window.set_cursor_icon(icon);
}
- pub fn set_title(&mut self, title: &str) {
- self.winit_window.set_title(title);
+
+ pub fn update_minimum_size(&mut self) {
+ let size = self.controller.minimum_size().map(|d| dim_to_size(d));
+ self.window.set_min_inner_size(size);
}
- /// Call to update the frame buffer to the new size of the window.
- pub fn resize_buffer(&mut self, dimensions: Dimensions) {
- if self.dimensions == dimensions { return }
- self.dimensions = dimensions;
- self.buffer.resize(dimensions);
- self.controller.on_resize(dimensions);
- self.render_hint = RenderHint::Redraw;
+ pub fn update_maximum_size(&mut self) {
+ let size = self.controller.maximum_size().map(|d| dim_to_size(d));
+ self.window.set_max_inner_size(size);
}
- pub fn set_cursor_icon(&mut self, icon: Option<CursorIcon>) {
- match icon {
- Some(icon) => self.winit_window.set_cursor_icon(icon),
- None => self.winit_window.set_cursor_icon(CursorIcon::Default),
- };
+ pub fn update_cursor_visible(&mut self) {
+ self.window.set_cursor_visible(self.controller.is_cursor_visible());
}
- /// Call this after a mouse click so that the cursor-hovering callbacks are
- /// rerun. This is useful where a click changes the UI layout and a new
- /// element that has an on-hover effect appears beneath the cursor.
- pub fn bump_mouse(&mut self) {
- if let Some(position) = self.cursor_position {
- self.controller.on_mouse_move(position)
+ pub fn update_resizable(&mut self) {
+ let is_resizable = self.controller.is_resizable();
+ self.window.set_resizable(is_resizable);
+ // Hack to force window to be impossible to resize on DWM, where the
+ // 'is_resizable' window attribute isn't respected.
+ if !is_resizable {
+ self.window.set_min_inner_size(Some(self.window.inner_size()));
+ self.window.set_max_inner_size(Some(self.window.inner_size()));
}
}
- pub fn move_mouse(&mut self, position: Point) {
- if self.cursor_position != Some(position) {
- self.cursor_position = Some(position);
- self.controller.on_mouse_move(position);
+ /// Resize the frame buffer to be the new size of the window.
+ pub fn resize(&mut self, dimensions: Dimensions) {
+ if self.dimensions == dimensions { return }
+ self.dimensions = dimensions;
+ self.buffer.resize(dimensions);
+ if let Some((width, height)) = dim_to_nonzero_size(dimensions) {
+ self.surface.resize(width, height).unwrap();
+ };
+ self.controller.on_resize(dimensions);
+ self.current_render_hint = RenderHint::Redraw;
+ }
+
+ pub fn move_cursor(&mut self, position: Point) {
+ // The cursor position is rounded to i32 from f64, so we need to ignore
+ // duplicate consecutive cursor positions.
+ if self.previous_cursor_position != Some(position) {
+ self.previous_cursor_position = Some(position);
+ self.controller.on_cursor_move(position);
}
}
- pub fn check_render_request(&mut self) {
+ pub fn handle_render_request(&mut self) {
if let RenderRequest::Render(hint) = self.controller.render_request() {
- self.render_hint &= hint;
- self.winit_window.request_redraw();
+ self.current_render_hint &= hint;
+ self.window.request_redraw();
}
}
pub fn render(&mut self) {
- self.controller.render(&mut self.buffer, self.render_hint);
- unsafe { self.graphics_context.blit(&self.buffer); }
- // Reset the render_hint back to the lowest variant.
- self.render_hint = RenderHint::Update;
+ let size = self.window.inner_size();
+ let dim = Dimensions::new(size.width, size.height);
+ self.resize(dim);
+ self.controller.on_render(&mut self.buffer, self.current_render_hint);
+ let buffer = self.buffer.as_u32_slice();
+ let mut surface = self.surface.buffer_mut().unwrap();
+ let buffer_len = buffer.len();
+ let surface_len = surface.len();
+ surface[..buffer_len].copy_from_slice(&buffer[..surface_len]);
+ surface.present().unwrap();
+ // Reset current_render_hint back to the lowest variant for the next frame.
+ self.current_render_hint = RenderHint::Update;
}
+}
- // pub fn render_gl(&mut self) {
- // self.gl_context.make_current();
- // self.controller.render_gl(&mut self.gl_context);
- // self.gl_context.swap_buffers();
- // self.gl_context.make_not_current();
- // }
+fn dim_to_size(dimensions: Dimensions) -> Size {
+ Size::Physical( PhysicalSize { width:dimensions.width, height:dimensions.height })
}
-trait GraphicsContext {
- /// Fill the graphics context with the contents of the provided buffer.
- unsafe fn blit(&mut self, buffer: &Buffer);
+fn dim_to_nonzero_size(dimensions: Dimensions) -> Option<(NonZeroU32, NonZeroU32)> {
+ let width = NonZeroU32::new(dimensions.width)?;
+ let height = NonZeroU32::new(dimensions.height)?;
+ return Some((width, height));
}