summaryrefslogtreecommitdiff
path: root/glfw/src/window.rs
diff options
context:
space:
mode:
Diffstat (limited to 'glfw/src/window.rs')
-rw-r--r--glfw/src/window.rs47
1 files changed, 46 insertions, 1 deletions
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<dyn Fn(Size)>;
type KeyCallback = Box<dyn Fn(Key, i32, KeyState, KeyModifiers)>;
+type CursorPositionCallback = Box<dyn Fn(CursorPosition)>;
thread_local! {
static FRAMEBUFFER_SIZE_CB: RefCell<Option<FramebufferSizeCb>> = RefCell::new(None);
static KEY_CALLBACK: RefCell<Option<KeyCallback>> = RefCell::new(None);
+static CURSOR_POS_CALLBACK: RefCell<Option<CursorPositionCallback>> = 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();
+ }
+}