From 4f31de2cdfa56a319cfb3a1ca356ae98e099e501 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 16 Mar 2024 17:30:15 +0100 Subject: feat: add function to set window cursor position callback --- glfw/src/window.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'glfw/src/window.rs') diff --git a/glfw/src/window.rs b/glfw/src/window.rs index a9512d6..0fb5978 100644 --- a/glfw/src/window.rs +++ b/glfw/src/window.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::ffi::{c_int, CString}; +use std::ffi::{c_double, c_int, CString}; use std::hint::unreachable_unchecked; use std::io::{stdout, Write}; use std::panic::catch_unwind; @@ -149,6 +149,23 @@ impl Window } } + /// Sets the cursor position callback. + /// + /// The callback is provided with the position, in screen coordinates, relative to the + /// upper-left corner of the content area of the window. + pub fn set_cursor_pos_callback(&self, callback: impl Fn(CursorPosition) + 'static) + { + CURSOR_POS_CALLBACK.with_borrow_mut(|cursor_pos_callback| { + *cursor_pos_callback = 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::glfwSetCursorPosCallback(self.handle, Some(cursor_pos_callback)); + } + } + /// Returns the last reported state of a keyboard key. /// /// # Errors @@ -633,10 +650,12 @@ pub struct CursorPosition type FramebufferSizeCb = Box; type KeyCallback = Box; +type CursorPositionCallback = Box; thread_local! { static FRAMEBUFFER_SIZE_CB: RefCell> = RefCell::new(None); static KEY_CALLBACK: RefCell> = RefCell::new(None); +static CURSOR_POS_CALLBACK: RefCell> = RefCell::new(None); } extern "C" fn framebuffer_size_callback( @@ -708,3 +727,29 @@ extern "C" fn key_callback( write!(stdout(), "ERROR: Panic in key callback").ok(); } } + +extern "C" fn cursor_pos_callback( + _window: *mut crate::ffi::GLFWwindow, + x_pos: c_double, + y_pos: c_double, +) +{ + // Unwinds are catched because unwinding from Rust code into foreign code is UB. + let res = catch_unwind(|| { + CURSOR_POS_CALLBACK + .try_with(|cursor_pos_callback| { + if let Some(cb) = cursor_pos_callback.borrow().as_deref() { + cb(CursorPosition { x: x_pos, y: y_pos }); + } + }) + .ok(); + }); + + if res.is_err() { + write!( + stdout(), + "ERROR: Cursor position callback panicked: {res:?}" + ) + .ok(); + } +} -- cgit v1.2.3-18-g5258