use std::ffi::CString; use std::num::NonZeroU32; use crate::{CWindowConfig, CWindowEvent}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct WindowConfig { pub title: Option, pub default_width: NonZeroU32, pub default_height: NonZeroU32, pub default_x: u32, pub default_y: u32, pub visible: bool, pub borderless_fullscreen: bool, } pub struct Window { pub(crate) ptr: *mut (), } pub enum WindowEvent { Other = 1, CloseRequest, ScaleFactorChange, Resume, RedrawRequest, } impl Drop for Window { fn drop(&mut self) { unsafe { crate::destroy_window(self.ptr) } } } impl Window { pub fn new(config: WindowConfig) -> Self { let title = config .title .map(|title| CString::new(title.as_bytes()).unwrap()); let config = CWindowConfig { default_width: config.default_width.get(), default_height: config.default_height.get(), default_x: config.default_x, default_y: config.default_y, visible: config.visible, borderless_fullscreen: config.borderless_fullscreen, title: title .as_ref() .map(|title| title.as_ptr()) .unwrap_or(std::ptr::null()), }; let window = unsafe { crate::create_window(config) }; drop(title); Self { ptr: window } } pub fn set_visible(&mut self, visible: bool) { unsafe { crate::set_visible(self.ptr, visible) } } pub fn set_title(&mut self, title: &str) { let string = CString::new(title.to_string().as_bytes()).unwrap(); let bytes = string.as_ptr(); unsafe { crate::set_title(self.ptr, bytes) } drop(string); } pub fn resize(&mut self, width: u32, height: u32) { unsafe { crate::resize_window(self.ptr, width, height) } } pub fn set_fullscreen(&mut self, fullscreen: bool) { unsafe { crate::set_fullscreen(self.ptr, fullscreen) } } fn translate_event(event: CWindowEvent) -> Option { let event = match event { CWindowEvent::AboutToWait => return None, CWindowEvent::Other => WindowEvent::Other, CWindowEvent::CloseRequest => WindowEvent::CloseRequest, CWindowEvent::ScaleFactorChange => WindowEvent::ScaleFactorChange, CWindowEvent::Resume => WindowEvent::Resume, CWindowEvent::RedrawRequest => WindowEvent::RedrawRequest, }; Some(event) } pub fn wait_for_event(&self) { unsafe { crate::wait_for_event(self.ptr) } } pub fn pop_event(&self) -> bool { unsafe { crate::pop_event(self.ptr) } } pub fn wait_for_resume(&mut self) { unsafe { crate::wait_for_resume(self.ptr) } } pub fn run(&mut self, mut handler: impl FnMut(&mut Window, Option)) -> ! { let window_ptr = self.ptr; unsafe { let closure = |c_event: CWindowEvent| { handler(self, Self::translate_event(c_event)); }; let closure_data: Box> = Box::new(Box::new(closure)); crate::set_event_handler(window_ptr, Box::into_raw(closure_data) as *mut _); } loop { if !self.pop_event() { unsafe { crate::run_event_handler(window_ptr, CWindowEvent::AboutToWait) }; } } } pub fn request_redraw(&mut self) { unsafe { crate::request_redraw(self.ptr) } } }