summaryrefslogtreecommitdiff
path: root/glfw
diff options
context:
space:
mode:
Diffstat (limited to 'glfw')
-rw-r--r--glfw/src/window.rs43
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();
+ }
+}