diff options
Diffstat (limited to 'glfw/src')
-rw-r--r-- | glfw/src/window.rs | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/glfw/src/window.rs b/glfw/src/window.rs index e3e6383..a080161 100644 --- a/glfw/src/window.rs +++ b/glfw/src/window.rs @@ -1,4 +1,6 @@ -use std::ffi::{CStr, CString}; +use std::cell::RefCell; +use std::ffi::{c_int, CStr, CString}; +use std::panic::catch_unwind; use std::ptr::null_mut; use crate::init::{initialize, Glfw}; @@ -140,6 +142,22 @@ impl Window height: height as u32, }) } + + pub fn set_framebuffer_size_callback(&self, callback: impl Fn(Size) + 'static) + { + FRAMEBUFFER_SIZE_CB.with_borrow_mut(|framebuffer_size_cb| { + *framebuffer_size_cb = Some(Box::new(callback)); + }); + + // SAFETY: The initialize function (called when the window is created) makes sure + // the current thread is the main thread + unsafe { + crate::ffi::glfwSetFramebufferSizeCallback( + self.handle, + Some(framebuffer_size_callback), + ); + } + } } /// Window size. @@ -148,3 +166,35 @@ pub struct Size pub width: u32, pub height: u32, } + +type FramebufferSizeCb = Box<dyn Fn(Size)>; + +thread_local! { +static FRAMEBUFFER_SIZE_CB: RefCell<Option<FramebufferSizeCb>> = RefCell::new(None); +} + +extern "C" fn framebuffer_size_callback( + _window: *mut crate::ffi::GLFWwindow, + c_width: c_int, + c_height: c_int, +) +{ + // Width and height can't possibly have their sign bit set + let width = u32::from_le_bytes(c_width.to_le_bytes()); + let height = u32::from_le_bytes(c_height.to_le_bytes()); + + // Unwinds are catched because unwinding from Rust code into foreign code is UB. + let res = catch_unwind(|| { + FRAMEBUFFER_SIZE_CB + .try_with(|framebuffer_size_cb| { + if let Some(cb) = framebuffer_size_cb.borrow().as_deref() { + cb(Size { width, height }); + } + }) + .ok(); + }); + + if res.is_err() { + println!("ERROR: Panic in framebuffer size callback"); + } +} |