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, cursor_position: Option, winit_window: WinitWindow, buffer: Buffer, dimensions: Dimensions, /// The most recent render request for this window. render_hint: RenderHint, graphics_context: Box, // gl_context: GlContext, } impl Window { pub unsafe fn new(event_loop: &EventLoopWindowTarget<()>, controller: Box) -> 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 = 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) { 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) { 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) { 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); }