diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index a21efef4ff4..81d8e510e60 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -115,6 +115,7 @@ selectend selectionchange selectstart serif +sessionavailable signalingstatechange squeeze squeezeend diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 2cd1359f9fd..bf78d8d584d 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -280,7 +280,8 @@ mod gen { }, layers: { enabled: bool, - } + }, + sessionavailable: bool, }, worklet: { blockingsleep: { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 4253f14f69c..437b147678d 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -17,6 +17,7 @@ use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMe use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementBinding::HTMLIFrameElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods; +use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use crate::dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter; use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods; @@ -2267,6 +2268,17 @@ impl Document { // Step 11. // TODO: ready for post-load tasks. + // The dom.webxr.sessionavailable pref allows webxr + // content to immediately begin a session without waiting for a user gesture. + // TODO: should this only happen on the first document loaded? + // https://immersive-web.github.io/webxr/#user-intention + // https://github.com/immersive-web/navigation/issues/10 + if pref!(dom.webxr.sessionavailable) { + if self.window.is_top_level() { + self.window.Navigator().Xr().dispatch_sessionavailable(); + } + } + // Step 12: completely loaded. // https://html.spec.whatwg.org/multipage/#completely-loaded // TODO: fully implement "completely loaded". diff --git a/components/script/dom/xrsystem.rs b/components/script/dom/xrsystem.rs index a2ba7946e62..798ba502aeb 100644 --- a/components/script/dom/xrsystem.rs +++ b/components/script/dom/xrsystem.rs @@ -7,6 +7,7 @@ use crate::dom::bindings::codegen::Bindings::XRSystemBinding::XRSessionInit; use crate::dom::bindings::codegen::Bindings::XRSystemBinding::{XRSessionMode, XRSystemMethods}; use crate::dom::bindings::conversions::{ConversionResult, FromJSValConvertible}; use crate::dom::bindings::error::Error; +use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; @@ -289,4 +290,26 @@ impl XRSystem { // This must be called _after_ the promise is resolved session.setup_initial_inputs(); } + + // https://github.com/immersive-web/navigation/issues/10 + pub fn dispatch_sessionavailable(&self) { + let xr = Trusted::new(self); + let global = self.global(); + let window = global.as_window(); + window + .task_manager() + .dom_manipulation_task_source() + .queue( + task!(fire_sessionavailable_event: move || { + // The sessionavailable event indicates user intent to enter an XR session + let xr = xr.root(); + let interacting = ScriptThread::is_user_interacting(); + ScriptThread::set_user_interacting(true); + xr.upcast::().fire_bubbling_event(atom!("sessionavailable")); + ScriptThread::set_user_interacting(interacting); + }), + window.upcast(), + ) + .unwrap(); + } } diff --git a/resources/prefs.json b/resources/prefs.json index cdbae48705f..0b219f7966a 100644 --- a/resources/prefs.json +++ b/resources/prefs.json @@ -41,6 +41,7 @@ "dom.webxr.glwindow.spherical": false, "dom.webxr.hands.enabled": false, "dom.webxr.layers.enabled": false, + "dom.webxr.sessionavailable": false, "dom.webxr.test": false, "dom.worklet.timeout_ms": 10, "gfx.subpixel-text-antialiasing.enabled": true, diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 521b124962b..f5bcd405ee8 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -14731,6 +14731,13 @@ null, {} ] + ], + "sessionavailable.html": [ + "dd9a071d05c4d696471be87428c12cea573cba60", + [ + null, + {} + ] ] } } diff --git a/tests/wpt/mozilla/meta/webxr/sessionavailable.html.ini b/tests/wpt/mozilla/meta/webxr/sessionavailable.html.ini new file mode 100644 index 00000000000..8bf6ba72fd8 --- /dev/null +++ b/tests/wpt/mozilla/meta/webxr/sessionavailable.html.ini @@ -0,0 +1,2 @@ +prefs: [dom.webxr.sessionavailable:true] + diff --git a/tests/wpt/mozilla/tests/webxr/sessionavailable.html b/tests/wpt/mozilla/tests/webxr/sessionavailable.html new file mode 100644 index 00000000000..dd9a071d05c --- /dev/null +++ b/tests/wpt/mozilla/tests/webxr/sessionavailable.html @@ -0,0 +1,20 @@ + + + + + + +