use std::ffi::{CStr, CString}; use std::ptr::null_mut; use crate::init::{initialize, Glfw}; use crate::{get_glfw_error, Error}; pub struct Window { _init: Glfw, handle: *mut crate::ffi::GLFWwindow, } impl Window { /// Creates a new window. /// /// # Errors /// Will return `Err` if /// - The title contains an internal nul byte /// - A GLFW error occurs pub fn create(size: &Size, title: &str) -> Result { let init = initialize()?; let c_title = CString::new(title).map_err(|_| Error::InternalNulByteInWindowTitle)?; // SAFETY: The initialize function makes sure the current thread is the main // thread let handle = unsafe { #[allow(clippy::cast_possible_wrap)] crate::ffi::glfwCreateWindow( size.width as i32, size.height as i32, c_title.as_ptr(), null_mut(), null_mut(), ) }; get_glfw_error()?; Ok(Self { _init: init, handle, }) } /// Makes the context of the window current for the calling thread. /// /// # Errors /// Will return `Err` if a GLFW platform error occurs or if no OpenGL context is /// present. pub fn make_context_current(&self) -> Result<(), Error> { unsafe { crate::ffi::glfwMakeContextCurrent(self.handle) }; get_glfw_error()?; Ok(()) } /// Returns the address of the specified OpenGL function, if it is supported by the /// current context. /// /// # Errors /// Will return `Err` if a GLFW platform error occurs or if no current context has /// been set. pub fn get_proc_address( &self, proc_name: &CStr, ) -> Result { let proc_addr = unsafe { crate::ffi::glfwGetProcAddress(proc_name.as_ptr()) }; get_glfw_error()?; // SAFETY: Is only None when a error has occured and that case is handled above Ok(unsafe { proc_addr.unwrap_unchecked() }) } /// Processes all pending events. /// /// # Errors /// Will return `Err` if a GLFW platform error occurs. pub fn poll_events(&self) -> Result<(), Error> { // SAFETY: The initialize function (called when the window is created) makes sure // the current thread is the main thread unsafe { crate::ffi::glfwPollEvents() }; get_glfw_error()?; Ok(()) } /// Swaps the front and back buffers of the window. /// /// # Errors /// Will return `Err` if a GLFW platform error occurs or if no OpenGL window context /// is present. pub fn swap_buffers(&self) -> Result<(), Error> { unsafe { crate::ffi::glfwSwapBuffers(self.handle); }; get_glfw_error()?; Ok(()) } /// Returns whether or not the window should close. #[must_use] pub fn should_close(&self) -> bool { let should_close = unsafe { crate::ffi::glfwWindowShouldClose(self.handle) }; should_close == crate::ffi::GLFW_TRUE } /// Retrieves the size of the window. /// /// # Errors /// Will return `Err` if a GLFW platform error occurs. pub fn size(&self) -> Result { let mut width = 0; let mut height = 0; // SAFETY: The initialize function (called when the window is created) makes sure // the current thread is the main thread unsafe { crate::ffi::glfwGetWindowSize(self.handle, &mut width, &mut height) }; get_glfw_error()?; #[allow(clippy::cast_sign_loss)] Ok(Size { width: width as u32, height: height as u32, }) } } /// Window size. pub struct Size { pub width: u32, pub height: u32, }