summaryrefslogtreecommitdiff
path: root/src/window.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2023-10-10 14:56:04 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2023-10-10 14:56:04 +1300
commita6e97019bd53e4478c846f8f636c18ecb53bece2 (patch)
tree69dada994e34cdfb4ddcef5a29c753f449407ec7 /src/window.rs
downloadphosphor-a6e97019bd53e4478c846f8f636c18ecb53bece2.zip
First commit, before upgrading winit to version 28.1
Diffstat (limited to 'src/window.rs')
-rw-r--r--src/window.rs136
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);
+}