diff --git a/CHANGELOG.md b/CHANGELOG.md index fb097296da..d67f74cdcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- On Web, implement cursor grabbing through the pointer lock API. - On X11, add mappings for numpad comma, numpad enter, numlock and pause. - On macOS, fix Pinyin IME input by reverting a change that intended to improve IME. - On Windows, fix a crash with transparent windows on Windows 11. diff --git a/FEATURES.md b/FEATURES.md index 96052a7671..484dacbc19 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -197,7 +197,7 @@ Legend: |----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | |Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ | |Mouse set location |✔️ |✔️ |✔️ |❓ |**N/A**|**N/A**|**N/A**| -|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|❓ | +|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|✔️ | |Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ | |Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ | |Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ | diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index 9725e8b6b8..8d68e5aaab 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -89,6 +89,20 @@ impl Canvas { }) } + pub fn set_cursor_grab(&self, grab: bool) -> Result<(), RootOE> { + if grab { + self.raw().request_pointer_lock(); + } else { + let window = web_sys::window() + .ok_or(os_error!(OsError("Failed to obtain window".to_owned())))?; + let document = window + .document() + .ok_or(os_error!(OsError("Failed to obtain document".to_owned())))?; + document.exit_pointer_lock(); + } + Ok(()) + } + pub fn set_attribute(&self, attribute: &str, value: &str) { self.common .raw diff --git a/src/platform_impl/web/web_sys/canvas/pointer_handler.rs b/src/platform_impl/web/web_sys/canvas/pointer_handler.rs index 5f6f321016..85a99eb8ab 100644 --- a/src/platform_impl/web/web_sys/canvas/pointer_handler.rs +++ b/src/platform_impl/web/web_sys/canvas/pointer_handler.rs @@ -79,9 +79,11 @@ impl PointerHandler { event::mouse_button(&event), event::mouse_modifiers(&event), ); - canvas - .set_pointer_capture(event.pointer_id()) - .expect("Failed to set pointer capture"); + + // Error is swallowed here since the error would occur every time the mouse is + // clicked when the cursor is grabbed, and there is probably not a situation where + // this could fail, that we care if it fails. + let _e = canvas.set_pointer_capture(event.pointer_id()); }, )); } diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 02bce57389..19fac1b93b 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -207,8 +207,11 @@ impl Window { } #[inline] - pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { - Err(ExternalError::NotSupported(NotSupportedError::new())) + pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> { + self.canvas + .borrow() + .set_cursor_grab(grab) + .map_err(|e| ExternalError::Os(e)) } #[inline] diff --git a/src/window.rs b/src/window.rs index 3e7100bc99..9410421d57 100644 --- a/src/window.rs +++ b/src/window.rs @@ -877,7 +877,7 @@ impl Window { /// ## Platform-specific /// /// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward. - /// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`]. + /// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`]. #[inline] pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> { self.window.set_cursor_grab(grab)