diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2023-10-10 14:56:04 +1300 |
---|---|---|
committer | Ben Bridle <bridle.benjamin@gmail.com> | 2023-10-10 14:56:04 +1300 |
commit | a6e97019bd53e4478c846f8f636c18ecb53bece2 (patch) | |
tree | 69dada994e34cdfb4ddcef5a29c753f449407ec7 /src/window.rs | |
download | phosphor-a6e97019bd53e4478c846f8f636c18ecb53bece2.zip |
First commit, before upgrading winit to version 28.1
Diffstat (limited to 'src/window.rs')
-rw-r--r-- | src/window.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/window.rs b/src/window.rs new file mode 100644 index 0000000..45e37c9 --- /dev/null +++ b/src/window.rs @@ -0,0 +1,136 @@ +mod x11; +use crate::*; +use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +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}; + +pub struct Window { + pub controller: Box<dyn WindowController>, + cursor_position: Option<Point>, + winit_window: WinitWindow, + buffer: Buffer, + dimensions: Dimensions, + /// The most recent render request for this window. + render_hint: RenderHint, + graphics_context: Box<dyn GraphicsContext>, + // gl_context: GlContext, +} + +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(); + + 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, + buffer: Buffer::new(Dimensions::ZERO), + dimensions: Dimensions::ZERO, + cursor_position: None, + } + } + + pub fn id(&self) -> WindowId { + self.winit_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 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 set_title(&mut self, title: &str) { + self.winit_window.set_title(title); + } + + /// 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 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), + }; + } + + /// 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 move_mouse(&mut self, position: Point) { + if self.cursor_position != Some(position) { + self.cursor_position = Some(position); + self.controller.on_mouse_move(position); + } + } + + pub fn check_render_request(&mut self) { + if let RenderRequest::Render(hint) = self.controller.render_request() { + self.render_hint &= hint; + self.winit_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; + } + + // 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(); + // } +} + +trait GraphicsContext { + /// Fill the graphics context with the contents of the provided buffer. + unsafe fn blit(&mut self, buffer: &Buffer); +} |