mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
webxr: Update XRInputSource Gamepad handling, FakeXRInputController (#33403)
* Disconnect XRInputSource gamepads on removal Signed-off-by: Daniel Adams <msub2official@gmail.com> * Update Cargo.lock Signed-off-by: Daniel Adams <msub2official@gmail.com> * Comments, adjustments Signed-off-by: Daniel Adams <msub2official@gmail.com> * Update expectations Signed-off-by: Daniel Adams <msub2official@gmail.com> --------- Signed-off-by: Daniel Adams <msub2official@gmail.com>
This commit is contained in:
parent
d9be9d6bd4
commit
08a4d751d7
11 changed files with 84 additions and 29 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -7971,7 +7971,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr"
|
name = "webxr"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#1a2186a5b33ae9e2e0b4fc15e9dc6095ae2e5fd0"
|
source = "git+https://github.com/servo/webxr#5587c9236bac0a8b7b87b3a95b22882400461b46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"euclid",
|
"euclid",
|
||||||
|
@ -7988,7 +7988,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr-api"
|
name = "webxr-api"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#1a2186a5b33ae9e2e0b4fc15e9dc6095ae2e5fd0"
|
source = "git+https://github.com/servo/webxr#5587c9236bac0a8b7b87b3a95b22882400461b46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
|
|
@ -11,8 +11,8 @@ use ipc_channel::ipc::IpcSender;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use profile_traits::ipc;
|
use profile_traits::ipc;
|
||||||
use webxr_api::{
|
use webxr_api::{
|
||||||
EntityType, Handedness, InputId, InputSource, MockDeviceMsg, MockInputInit, MockRegion,
|
EntityType, Handedness, InputId, InputSource, MockButton, MockDeviceMsg, MockInputInit,
|
||||||
MockViewInit, MockViewsInit, MockWorld, TargetRayMode, Triangle, Visibility,
|
MockRegion, MockViewInit, MockViewsInit, MockWorld, TargetRayMode, Triangle, Visibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit;
|
use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit;
|
||||||
|
@ -30,7 +30,7 @@ use crate::dom::bindings::error::{Error, Fallible};
|
||||||
use crate::dom::bindings::refcounted::TrustedPromise;
|
use crate::dom::bindings::refcounted::TrustedPromise;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::fakexrinputcontroller::FakeXRInputController;
|
use crate::dom::fakexrinputcontroller::{init_to_mock_buttons, FakeXRInputController};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
|
@ -267,7 +267,10 @@ impl FakeXRDeviceMethods for FakeXRDevice {
|
||||||
|
|
||||||
let profiles = init.profiles.iter().cloned().map(String::from).collect();
|
let profiles = init.profiles.iter().cloned().map(String::from).collect();
|
||||||
|
|
||||||
// XXXManishearth deal with supportedButtons and selection*
|
let mut supported_buttons = vec![];
|
||||||
|
if let Some(ref buttons) = init.supportedButtons {
|
||||||
|
supported_buttons.extend(init_to_mock_buttons(buttons));
|
||||||
|
}
|
||||||
|
|
||||||
let source = InputSource {
|
let source = InputSource {
|
||||||
handedness,
|
handedness,
|
||||||
|
@ -282,6 +285,7 @@ impl FakeXRDeviceMethods for FakeXRDevice {
|
||||||
source,
|
source,
|
||||||
pointer_origin,
|
pointer_origin,
|
||||||
grip_origin,
|
grip_origin,
|
||||||
|
supported_buttons,
|
||||||
};
|
};
|
||||||
|
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
|
|
|
@ -5,15 +5,18 @@
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use webxr_api::{
|
use webxr_api::{
|
||||||
Handedness, InputId, MockDeviceMsg, MockInputMsg, SelectEvent, SelectKind, TargetRayMode,
|
Handedness, InputId, MockButton, MockButtonType, MockDeviceMsg, MockInputMsg, SelectEvent,
|
||||||
|
SelectKind, TargetRayMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::dom::bindings::codegen::Bindings::FakeXRDeviceBinding::FakeXRRigidTransformInit;
|
use crate::dom::bindings::codegen::Bindings::FakeXRDeviceBinding::FakeXRRigidTransformInit;
|
||||||
use crate::dom::bindings::codegen::Bindings::FakeXRInputControllerBinding::FakeXRInputControllerMethods;
|
use crate::dom::bindings::codegen::Bindings::FakeXRInputControllerBinding::{
|
||||||
|
FakeXRButtonStateInit, FakeXRButtonType, FakeXRInputControllerMethods,
|
||||||
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
|
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
|
||||||
XRHandedness, XRTargetRayMode,
|
XRHandedness, XRTargetRayMode,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::error::Fallible;
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
@ -136,4 +139,56 @@ impl FakeXRInputControllerMethods for FakeXRInputController {
|
||||||
let t = profiles.into_iter().map(String::from).collect();
|
let t = profiles.into_iter().map(String::from).collect();
|
||||||
self.send_message(MockInputMsg::SetProfiles(t));
|
self.send_message(MockInputMsg::SetProfiles(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-setsupportedbuttons>
|
||||||
|
fn SetSupportedButtons(&self, supported_buttons: Vec<FakeXRButtonStateInit>) {
|
||||||
|
let supported = init_to_mock_buttons(&supported_buttons);
|
||||||
|
self.send_message(MockInputMsg::SetSupportedButtons(supported));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-updatebuttonstate>
|
||||||
|
fn UpdateButtonState(&self, button_state: &FakeXRButtonStateInit) -> Fallible<()> {
|
||||||
|
// https://immersive-web.github.io/webxr-test-api/#validate-a-button-state
|
||||||
|
if (button_state.pressed || *button_state.pressedValue > 0.0) && !button_state.touched {
|
||||||
|
return Err(Error::Type("Pressed button must also be touched".into()));
|
||||||
|
}
|
||||||
|
if *button_state.pressedValue < 0.0 {
|
||||||
|
return Err(Error::Type("Pressed value must be non-negative".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Steps 3-5 of updateButtonState
|
||||||
|
// Passing the one WPT test that utilizes this will require additional work
|
||||||
|
// to specify gamepad button/axes list lengths, as well as passing that info
|
||||||
|
// to the constructor of XRInputSource
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FakeXRButtonType> for MockButtonType {
|
||||||
|
fn from(b: FakeXRButtonType) -> Self {
|
||||||
|
match b {
|
||||||
|
FakeXRButtonType::Grip => MockButtonType::Grip,
|
||||||
|
FakeXRButtonType::Touchpad => MockButtonType::Touchpad,
|
||||||
|
FakeXRButtonType::Thumbstick => MockButtonType::Thumbstick,
|
||||||
|
FakeXRButtonType::Optional_button => MockButtonType::OptionalButton,
|
||||||
|
FakeXRButtonType::Optional_thumbstick => MockButtonType::OptionalThumbstick,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://immersive-web.github.io/webxr-test-api/#parse-supported-buttons>
|
||||||
|
pub fn init_to_mock_buttons(buttons: &[FakeXRButtonStateInit]) -> Vec<MockButton> {
|
||||||
|
let supported: Vec<MockButton> = buttons
|
||||||
|
.iter()
|
||||||
|
.map(|b| MockButton {
|
||||||
|
button_type: b.buttonType.into(),
|
||||||
|
pressed: b.pressed,
|
||||||
|
touched: b.touched,
|
||||||
|
pressed_value: *b.pressedValue,
|
||||||
|
x_value: *b.xValue,
|
||||||
|
y_value: *b.yValue,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
supported
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ interface FakeXRInputController {
|
||||||
undefined endSelection();
|
undefined endSelection();
|
||||||
undefined simulateSelect();
|
undefined simulateSelect();
|
||||||
|
|
||||||
// void setSupportedButtons(sequence<FakeXRButtonStateInit> supportedButtons);
|
undefined setSupportedButtons(sequence<FakeXRButtonStateInit> supportedButtons);
|
||||||
// void updateButtonState(FakeXRButtonStateInit buttonState);
|
[Throws] undefined updateButtonState(FakeXRButtonStateInit buttonState);
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary FakeXRInputSourceInit {
|
dictionary FakeXRInputSourceInit {
|
||||||
|
|
|
@ -110,6 +110,10 @@ impl XRInputSource {
|
||||||
self.gamepad.map_and_normalize_axes(i, *value as f64);
|
self.gamepad.map_and_normalize_axes(i, *value as f64);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gamepad(&self) -> &DomRoot<Gamepad> {
|
||||||
|
&self.gamepad
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRInputSourceMethods for XRInputSource {
|
impl XRInputSourceMethods for XRInputSource {
|
||||||
|
|
|
@ -69,6 +69,7 @@ impl XRInputSourceArray {
|
||||||
let mut input_sources = self.input_sources.borrow_mut();
|
let mut input_sources = self.input_sources.borrow_mut();
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) {
|
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) {
|
||||||
|
i.gamepad().update_connected(false, false);
|
||||||
[DomRoot::from_ref(&**i)]
|
[DomRoot::from_ref(&**i)]
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -94,6 +95,7 @@ impl XRInputSourceArray {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let root;
|
let root;
|
||||||
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) {
|
let removed = if let Some(i) = input_sources.iter().find(|i| i.id() == id) {
|
||||||
|
i.gamepad().update_connected(false, false);
|
||||||
root = [DomRoot::from_ref(&**i)];
|
root = [DomRoot::from_ref(&**i)];
|
||||||
&root as &[_]
|
&root as &[_]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,6 +33,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::Wind
|
||||||
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::{
|
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::{
|
||||||
XRHitTestOptionsInit, XRHitTestTrackableType,
|
XRHitTestOptionsInit, XRHitTestTrackableType,
|
||||||
};
|
};
|
||||||
|
use crate::dom::bindings::codegen::Bindings::XRInputSourceArrayBinding::XRInputSourceArray_Binding::XRInputSourceArrayMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType;
|
use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::{
|
use crate::dom::bindings::codegen::Bindings::XRRenderStateBinding::{
|
||||||
XRRenderStateInit, XRRenderStateMethods,
|
XRRenderStateInit, XRRenderStateMethods,
|
||||||
|
@ -867,6 +868,11 @@ impl XRSessionMethods for XRSession {
|
||||||
self.ended.set(true);
|
self.ended.set(true);
|
||||||
global.as_window().Navigator().Xr().end_session(self);
|
global.as_window().Navigator().Xr().end_session(self);
|
||||||
self.session.borrow_mut().end_session();
|
self.session.borrow_mut().end_session();
|
||||||
|
// Disconnect any still-attached XRInputSources
|
||||||
|
for source in 0..self.input_sources.Length() {
|
||||||
|
self.input_sources
|
||||||
|
.remove_input_source(self, InputId(source));
|
||||||
|
}
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[events_session_squeeze.https.html]
|
[events_session_squeeze.https.html]
|
||||||
expected: ERROR
|
expected: TIMEOUT
|
||||||
[XRInputSources primary input presses properly fires off the right events - webgl]
|
[XRInputSources primary input presses properly fires off the right events - webgl]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[xrInputSource_gamepad_disconnect.https.html]
|
|
||||||
expected: ERROR
|
|
||||||
[WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl2]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[events_session_squeeze.https.html]
|
[events_session_squeeze.https.html]
|
||||||
expected: ERROR
|
expected: TIMEOUT
|
||||||
[XRInputSources primary input presses properly fires off the right events - webgl]
|
[XRInputSources primary input presses properly fires off the right events - webgl]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[xrInputSource_gamepad_disconnect.https.html]
|
|
||||||
expected: ERROR
|
|
||||||
[WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl2]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
||||||
[WebXR InputSource's gamepad gets disconnected when the input source is removed - webgl]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue