diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-10-04 04:31:42 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-04 04:31:42 -0400 |
commit | ea4e3aee91ede11a00b17c3d806e305f4a7f5a92 (patch) | |
tree | 042472ffdb9f8d58f0656a750f5d024981b5443d /components/script/dom | |
parent | 30e5cfcdb07166bfa12aae5e0d6086432d7ebd9f (diff) | |
parent | 931f0b12de9df385dfff0ad438c88105fe4b6cfe (diff) | |
download | servo-ea4e3aee91ede11a00b17c3d806e305f4a7f5a92.tar.gz servo-ea4e3aee91ede11a00b17c3d806e305f4a7f5a92.zip |
Auto merge of #24362 - Manishearth:input-selections, r=asajeffrey
Support input tracking loss and selection events in XR
Fixes https://github.com/servo/servo/issues/24192
Requires https://github.com/servo/webxr/pull/65
r? @jdm @asajeffrey
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24362)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/XRInputSourceEvent.webidl | 17 | ||||
-rw-r--r-- | components/script/dom/webidls/XRSession.webidl | 6 | ||||
-rw-r--r-- | components/script/dom/xrframe.rs | 12 | ||||
-rw-r--r-- | components/script/dom/xrinputsourceevent.rs | 90 | ||||
-rw-r--r-- | components/script/dom/xrsession.rs | 58 | ||||
-rw-r--r-- | components/script/dom/xrspace.rs | 6 |
7 files changed, 181 insertions, 9 deletions
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index d6a6c30b823..598832403e0 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -549,6 +549,7 @@ pub mod xmlserializer; pub mod xr; pub mod xrframe; pub mod xrinputsource; +pub mod xrinputsourceevent; pub mod xrpose; pub mod xrreferencespace; pub mod xrrenderstate; diff --git a/components/script/dom/webidls/XRInputSourceEvent.webidl b/components/script/dom/webidls/XRInputSourceEvent.webidl new file mode 100644 index 00000000000..f1ffbf2a799 --- /dev/null +++ b/components/script/dom/webidls/XRInputSourceEvent.webidl @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// https://immersive-web.github.io/webxr/#xrinputsourceevent-interface + +[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] +interface XRInputSourceEvent : Event { + [Throws] constructor(DOMString type, XRInputSourceEventInit eventInitDict); + [SameObject] readonly attribute XRFrame frame; + [SameObject] readonly attribute XRInputSource inputSource; +}; + +dictionary XRInputSourceEventInit : EventInit { + required XRFrame frame; + required XRInputSource inputSource; +}; diff --git a/components/script/dom/webidls/XRSession.webidl b/components/script/dom/webidls/XRSession.webidl index 6d946ccef55..820ef11dc70 100644 --- a/components/script/dom/webidls/XRSession.webidl +++ b/components/script/dom/webidls/XRSession.webidl @@ -39,8 +39,8 @@ interface XRSession : EventTarget { // attribute EventHandler onblur; // attribute EventHandler onfocus; attribute EventHandler onend; - // attribute EventHandler onselect; + attribute EventHandler onselect; // attribute EventHandler oninputsourceschange; - // attribute EventHandler onselectstart; - // attribute EventHandler onselectend; + attribute EventHandler onselectstart; + attribute EventHandler onselectend; }; diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index 29572c02300..6c67d896f81 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -93,8 +93,16 @@ impl XRFrameMethods for XRFrame { if !self.active.get() { return Err(Error::InvalidState); } - let space = space.get_pose(&self.data); - let relative_to = relative_to.get_pose(&self.data); + let space = if let Some(space) = space.get_pose(&self.data) { + space + } else { + return Ok(None); + }; + let relative_to = if let Some(r) = relative_to.get_pose(&self.data) { + r + } else { + return Ok(None); + }; let pose = relative_to.inverse().pre_transform(&space); Ok(Some(XRPose::new(&self.global(), pose))) } diff --git a/components/script/dom/xrinputsourceevent.rs b/components/script/dom/xrinputsourceevent.rs new file mode 100644 index 00000000000..aa177f1df9a --- /dev/null +++ b/components/script/dom/xrinputsourceevent.rs @@ -0,0 +1,90 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods; +use crate::dom::bindings::codegen::Bindings::XRInputSourceEventBinding::{ + self, XRInputSourceEventMethods, +}; +use crate::dom::bindings::error::Fallible; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::str::DOMString; +use crate::dom::event::Event; +use crate::dom::globalscope::GlobalScope; +use crate::dom::window::Window; +use crate::dom::xrframe::XRFrame; +use crate::dom::xrinputsource::XRInputSource; +use dom_struct::dom_struct; +use servo_atoms::Atom; + +#[dom_struct] +pub struct XRInputSourceEvent { + event: Event, + frame: Dom<XRFrame>, + source: Dom<XRInputSource>, +} + +impl XRInputSourceEvent { + #[allow(unrooted_must_root)] + fn new_inherited(frame: &XRFrame, source: &XRInputSource) -> XRInputSourceEvent { + XRInputSourceEvent { + event: Event::new_inherited(), + frame: Dom::from_ref(frame), + source: Dom::from_ref(source), + } + } + + pub fn new( + global: &GlobalScope, + type_: Atom, + bubbles: bool, + cancelable: bool, + frame: &XRFrame, + source: &XRInputSource, + ) -> DomRoot<XRInputSourceEvent> { + let trackevent = reflect_dom_object( + Box::new(XRInputSourceEvent::new_inherited(frame, source)), + global, + XRInputSourceEventBinding::Wrap, + ); + { + let event = trackevent.upcast::<Event>(); + event.init_event(type_, bubbles, cancelable); + } + trackevent + } + + pub fn Constructor( + window: &Window, + type_: DOMString, + init: &XRInputSourceEventBinding::XRInputSourceEventInit, + ) -> Fallible<DomRoot<XRInputSourceEvent>> { + Ok(XRInputSourceEvent::new( + &window.global(), + Atom::from(type_), + init.parent.bubbles, + init.parent.cancelable, + &init.frame, + &init.inputSource, + )) + } +} + +impl XRInputSourceEventMethods for XRInputSourceEvent { + // https://immersive-web.github.io/webxr/#dom-xrinputsourceeventinit-frame + fn Frame(&self) -> DomRoot<XRFrame> { + DomRoot::from_ref(&*self.frame) + } + + // https://immersive-web.github.io/webxr/#dom-xrinputsourceeventinit-inputsource + fn InputSource(&self) -> DomRoot<XRInputSource> { + DomRoot::from_ref(&*self.source) + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index dacfc373540..e7a3fab4677 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -33,6 +33,7 @@ use crate::dom::promise::Promise; use crate::dom::webglframebuffer::WebGLFramebufferAttachmentRoot; use crate::dom::xrframe::XRFrame; use crate::dom::xrinputsource::XRInputSource; +use crate::dom::xrinputsourceevent::XRInputSourceEvent; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrenderstate::XRRenderState; use crate::dom::xrsessionevent::XRSessionEvent; @@ -48,7 +49,7 @@ use profile_traits::ipc; use std::cell::Cell; use std::mem; use std::rc::Rc; -use webxr_api::{self, Event as XREvent, Frame, Session}; +use webxr_api::{self, Event as XREvent, Frame, SelectEvent, Session}; #[dom_struct] pub struct XRSession { @@ -170,6 +171,52 @@ impl XRSession { let event = XRSessionEvent::new(&self.global(), atom!("end"), false, false, self); event.upcast::<Event>().fire(self.upcast()); }, + XREvent::Select(input, kind, frame) => { + // https://immersive-web.github.io/webxr/#primary-action + let source = self + .input_sources + .borrow_mut() + .iter() + .find(|s| s.id() == input) + .map(|x| DomRoot::from_ref(&**x)); + if let Some(source) = source { + let frame = XRFrame::new(&self.global(), self, frame); + frame.set_active(true); + if kind == SelectEvent::Start { + let event = XRInputSourceEvent::new( + &self.global(), + atom!("selectstart"), + false, + false, + &frame, + &source, + ); + event.upcast::<Event>().fire(self.upcast()); + } else { + if kind == SelectEvent::Select { + let event = XRInputSourceEvent::new( + &self.global(), + atom!("select"), + false, + false, + &frame, + &source, + ); + event.upcast::<Event>().fire(self.upcast()); + } + let event = XRInputSourceEvent::new( + &self.global(), + atom!("selectend"), + false, + false, + &frame, + &source, + ); + event.upcast::<Event>().fire(self.upcast()); + } + frame.set_active(false); + } + }, _ => (), // XXXManishearth TBD } } @@ -244,6 +291,15 @@ impl XRSessionMethods for XRSession { /// https://immersive-web.github.io/webxr/#eventdef-xrsession-end event_handler!(end, GetOnend, SetOnend); + /// https://immersive-web.github.io/webxr/#eventdef-xrsession-select + event_handler!(select, GetOnselect, SetOnselect); + + /// https://immersive-web.github.io/webxr/#eventdef-xrsession-selectstart + event_handler!(selectstart, GetOnselectstart, SetOnselectstart); + + /// https://immersive-web.github.io/webxr/#eventdef-xrsession-selectend + event_handler!(selectend, GetOnselectend, SetOnselectend); + /// https://immersive-web.github.io/webxr/#dom-xrsession-mode fn Mode(&self) -> XRSessionMode { XRSessionMode::Immersive_vr diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 6fa00d1cffe..ce68e786927 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -57,9 +57,9 @@ impl XRSpace { /// The reference origin used is common between all /// get_pose calls for spaces from the same device, so this can be used to compare /// with other spaces - pub fn get_pose(&self, base_pose: &Frame) -> ApiPose { + pub fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> { if let Some(reference) = self.downcast::<XRReferenceSpace>() { - reference.get_pose(base_pose) + Some(reference.get_pose(base_pose)) } else if let Some(source) = self.input_source.get() { // XXXManishearth we should be able to request frame information // for inputs when necessary instead of always loading it @@ -72,7 +72,7 @@ impl XRSpace { .iter() .find(|i| i.id == id) .expect("no input found"); - cast_transform(frame.target_ray_origin) + frame.target_ray_origin.map(cast_transform) } else { unreachable!() } |