From 35df7a829852c1dfc51be6b02678e631ce7f4d1b Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 18 May 2024 17:31:24 +0200 Subject: feat(glfw): add Window set focus callback function --- glfw/src/window.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/glfw/src/window.rs b/glfw/src/window.rs index 40eb300..8ccb1d1 100644 --- a/glfw/src/window.rs +++ b/glfw/src/window.rs @@ -202,6 +202,20 @@ impl Window } } + /// Sets the callback called when the window gains or loses input focus. + pub fn set_focus_callback(&self, callback: impl Fn(bool) + 'static) + { + FOCUS_CALLBACK.with_borrow_mut(|focus_cb| { + *focus_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::glfwSetWindowFocusCallback(self.handle, Some(focus_callback)); + } + } + /// Returns the last reported state of a keyboard key. /// /// # Errors @@ -680,6 +694,7 @@ type FramebufferSizeCb = Box; type KeyCallback = Box; type CursorPositionCallback = Box; type MouseButtonCallback = Box; +type FocusCallback = Box; thread_local! { static CLOSE_CALLBACK: RefCell> = RefCell::new(None); @@ -687,6 +702,7 @@ static FRAMEBUFFER_SIZE_CB: RefCell> = RefCell::new(No static KEY_CALLBACK: RefCell> = RefCell::new(None); static CURSOR_POS_CALLBACK: RefCell> = RefCell::new(None); static MOUSE_BUTTON_CALLBACK: RefCell> = RefCell::new(None); +static FOCUS_CALLBACK: RefCell> = RefCell::new(None); } extern "C" fn close_callback(_window: *mut crate::ffi::GLFWwindow) @@ -845,3 +861,30 @@ extern "C" fn mouse_button_callback( write!(stdout(), "ERROR: Mouse button callback panicked: {res:?}").ok(); } } + +extern "C" fn focus_callback(_window: *mut crate::ffi::GLFWwindow, focused: c_int) +{ + let is_focused = if focused == crate::ffi::GLFW_TRUE { + true + } else if focused == crate::ffi::GLFW_FALSE { + false + } else { + write!(stdout(), "Invalid focus state {focused}").ok(); + return; + }; + + // Unwinds are catched because unwinding from Rust code into foreign code is UB. + let res = catch_unwind(|| { + FOCUS_CALLBACK + .try_with(|focus_callback| { + if let Some(cb) = focus_callback.borrow().as_deref() { + cb(is_focused); + } + }) + .ok(); + }); + + if res.is_err() { + write!(stdout(), "ERROR: Focus callback panicked: {res:?}").ok(); + } +} -- cgit v1.2.3-18-g5258