Add cursor grab for web target (#2025)

* Add cursor grab

* Update feature matrix, changelog and platform information

* Add proper error propagation

* Remove "expect" from fallible code

    code would crash if handling pointer capture outside of winit on
    every mouse click

    we swallow the error since we could not think of a case where this
    would fail in a way that would want to handle that it fails

* Remove unnecessary implementation comment

Co-authored-by: Will Crichton <wcrichto@cs.stanford.edu>
This commit is contained in:
TotalKrill 2022-01-05 11:13:46 +01:00 committed by GitHub
parent 25ff30ee8c
commit c5c99d2357
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 7 deletions

View file

@ -1,5 +1,6 @@
# Unreleased # Unreleased
- On Web, implement cursor grabbing through the pointer lock API.
- On X11, add mappings for numpad comma, numpad enter, numlock and pause. - 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 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. - On Windows, fix a crash with transparent windows on Windows 11.

View file

@ -197,7 +197,7 @@ Legend:
|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- | |----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- |
|Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ | |Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ |
|Mouse set location |✔️ |✔️ |✔️ |❓ |**N/A**|**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**|✔️ | |Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ |
|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ | |Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ |
|Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ | |Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ |

View file

@ -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) { pub fn set_attribute(&self, attribute: &str, value: &str) {
self.common self.common
.raw .raw

View file

@ -79,9 +79,11 @@ impl PointerHandler {
event::mouse_button(&event), event::mouse_button(&event),
event::mouse_modifiers(&event), event::mouse_modifiers(&event),
); );
canvas
.set_pointer_capture(event.pointer_id()) // Error is swallowed here since the error would occur every time the mouse is
.expect("Failed to set pointer capture"); // 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());
}, },
)); ));
} }

View file

@ -207,8 +207,11 @@ impl Window {
} }
#[inline] #[inline]
pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> { pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
Err(ExternalError::NotSupported(NotSupportedError::new())) self.canvas
.borrow()
.set_cursor_grab(grab)
.map_err(|e| ExternalError::Os(e))
} }
#[inline] #[inline]

View file

@ -877,7 +877,7 @@ impl Window {
/// ## Platform-specific /// ## Platform-specific
/// ///
/// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward. /// - **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] #[inline]
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> { pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
self.window.set_cursor_grab(grab) self.window.set_cursor_grab(grab)