diff options
author | HampusM <hampus@hampusmat.com> | 2023-10-07 20:00:16 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-10-07 20:00:16 +0200 |
commit | b34b393f7b07495ca92ff5b0ce79d4c391abe0ca (patch) | |
tree | 062ae1cf150596bdde32abd7b52346b0b0e817bc | |
parent | d1be0566969974bd70f2d77915b6936095c894c6 (diff) |
feat(glfw): add function to set framebuffer size callback
-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"); + } +} |