diff options
Diffstat (limited to 'glfw/src')
-rw-r--r-- | glfw/src/window.rs | 43 |
1 files changed, 43 insertions, 0 deletions
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<dyn Fn(Size)>; type KeyCallback = Box<dyn Fn(Key, i32, KeyState, KeyModifiers)>; type CursorPositionCallback = Box<dyn Fn(CursorPosition)>; type MouseButtonCallback = Box<dyn Fn(MouseButton, MouseButtonState, KeyModifiers)>; +type FocusCallback = Box<dyn Fn(bool)>; thread_local! { static CLOSE_CALLBACK: RefCell<Option<CloseCallback>> = RefCell::new(None); @@ -687,6 +702,7 @@ static FRAMEBUFFER_SIZE_CB: RefCell<Option<FramebufferSizeCb>> = RefCell::new(No static KEY_CALLBACK: RefCell<Option<KeyCallback>> = RefCell::new(None); static CURSOR_POS_CALLBACK: RefCell<Option<CursorPositionCallback>> = RefCell::new(None); static MOUSE_BUTTON_CALLBACK: RefCell<Option<MouseButtonCallback>> = RefCell::new(None); +static FOCUS_CALLBACK: RefCell<Option<FocusCallback>> = 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(); + } +} |