Skip to content

Commit

Permalink
Auto merge of #25463 - Manishearth:input-mocking, r=asajeffrey
Browse files Browse the repository at this point in the history
Add input mocking, input sources change event

Depends on  servo/webxr#118

Also fixes some bugs I found.

Wanted to finish and merge this before I started on hit testing since the transient hit test stuff might have overlap.

There are a bunch of missing mock pieces that I'll probably do in a separate PR.

Still need to run tests.

Some things I skipped:
 - Doing handedness/target ray setting: See immersive-web/webxr-test-api#46 , this would require making our impl support these changing
 - Handling button initial state: Would require some mock changes, but I ran out of time
 - Handling profiles/etc: We don't yet have impl support for these

r? @jdm
  • Loading branch information
bors-servo committed Jan 9, 2020
2 parents 95e6c71 + 94e8ce5 commit dbee7f7
Show file tree
Hide file tree
Showing 30 changed files with 485 additions and 79 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/atoms/static_atoms.txt
Expand Up @@ -44,6 +44,7 @@ iceconnectionstatechange
icegatheringstatechange
image
input
inputsourceschange
invalid
keydown
keypress
Expand Down
3 changes: 2 additions & 1 deletion components/script/dom/bindings/trace.rs
Expand Up @@ -534,7 +534,8 @@ unsafe_no_jsmanaged_fields!(
webxr_api::Registry,
webxr_api::Session,
webxr_api::Frame,
webxr_api::InputSource
webxr_api::InputSource,
webxr_api::InputId
);
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
Expand Down
89 changes: 87 additions & 2 deletions components/script/dom/fakexrdevice.rs
Expand Up @@ -5,11 +5,17 @@
use crate::dom::bindings::codegen::Bindings::FakeXRDeviceBinding::{
self, FakeXRDeviceMethods, FakeXRRigidTransformInit, FakeXRViewInit,
};
use crate::dom::bindings::codegen::Bindings::FakeXRInputControllerBinding::FakeXRInputSourceInit;
use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
XRHandedness, XRTargetRayMode,
};
use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRVisibilityState;
use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::refcounted::TrustedPromise;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::fakexrinputcontroller::FakeXRInputController;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::task_source::TaskSource;
Expand All @@ -19,21 +25,28 @@ use euclid::{RigidTransform3D, Rotation3D, Transform3D, Vector3D};
use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER;
use profile_traits::ipc;
use std::cell::Cell;
use std::rc::Rc;
use webxr_api::{MockDeviceMsg, MockViewInit, MockViewsInit};
use webxr_api::{
Handedness, InputId, InputSource, MockDeviceMsg, MockInputInit, MockViewInit, MockViewsInit,
TargetRayMode, Visibility,
};

#[dom_struct]
pub struct FakeXRDevice {
reflector: Reflector,
#[ignore_malloc_size_of = "defined in ipc-channel"]
sender: IpcSender<MockDeviceMsg>,
#[ignore_malloc_size_of = "defined in webxr-api"]
next_input_id: Cell<InputId>,
}

impl FakeXRDevice {
pub fn new_inherited(sender: IpcSender<MockDeviceMsg>) -> FakeXRDevice {
FakeXRDevice {
reflector: Reflector::new(),
sender,
next_input_id: Cell::new(InputId(0)),
}
}

Expand Down Expand Up @@ -163,7 +176,59 @@ impl FakeXRDeviceMethods for FakeXRDevice {
Ok(())
}

/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-simulatevisibilitychange
fn SimulateVisibilityChange(&self, v: XRVisibilityState) {
let v = match v {
XRVisibilityState::Visible => Visibility::Visible,
XRVisibilityState::Visible_blurred => Visibility::VisibleBlurred,
XRVisibilityState::Hidden => Visibility::Hidden,
};
let _ = self.sender.send(MockDeviceMsg::VisibilityChange(v));
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-simulateinputsourceconnection
fn SimulateInputSourceConnection(
&self,
init: &FakeXRInputSourceInit,
) -> Fallible<DomRoot<FakeXRInputController>> {
let id = self.next_input_id.get();
self.next_input_id.set(InputId(id.0 + 1));

let handedness = init.handedness.into();
let target_ray_mode = init.targetRayMode.into();

let pointer_origin = Some(get_origin(&init.pointerOrigin)?);

let grip_origin = if let Some(ref g) = init.gripOrigin {
Some(get_origin(g)?)
} else {
None
};

// XXXManishearth deal with profiles, supportedButtons, selection*

let source = InputSource {
handedness,
target_ray_mode,
id,
supports_grip: true,
};

let init = MockInputInit {
source,
pointer_origin,
grip_origin,
};

let global = self.global();
let _ = self.sender.send(MockDeviceMsg::AddInputSource(init));

let controller = FakeXRInputController::new(&global, self.sender.clone(), id);

Ok(controller)
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-disconnect
fn Disconnect(&self) -> Rc<Promise> {
let global = self.global();
let p = Promise::new(&global);
Expand All @@ -186,3 +251,23 @@ impl FakeXRDeviceMethods for FakeXRDevice {
p
}
}

impl From<XRHandedness> for Handedness {
fn from(h: XRHandedness) -> Self {
match h {
XRHandedness::None => Handedness::None,
XRHandedness::Left => Handedness::Left,
XRHandedness::Right => Handedness::Right,
}
}
}

impl From<XRTargetRayMode> for TargetRayMode {
fn from(t: XRTargetRayMode) -> Self {
match t {
XRTargetRayMode::Gaze => TargetRayMode::Gaze,
XRTargetRayMode::Tracked_pointer => TargetRayMode::TrackedPointer,
XRTargetRayMode::Screen => TargetRayMode::Screen,
}
}
}
106 changes: 106 additions & 0 deletions components/script/dom/fakexrinputcontroller.rs
@@ -0,0 +1,106 @@
/* 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::FakeXRDeviceBinding::FakeXRRigidTransformInit;
use crate::dom::bindings::codegen::Bindings::FakeXRInputControllerBinding::{
self, FakeXRInputControllerMethods,
};
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::fakexrdevice::get_origin;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use ipc_channel::ipc::IpcSender;
use webxr_api::{InputId, MockDeviceMsg, MockInputMsg, SelectEvent, SelectKind};

#[dom_struct]
pub struct FakeXRInputController {
reflector: Reflector,
#[ignore_malloc_size_of = "defined in ipc-channel"]
sender: IpcSender<MockDeviceMsg>,
#[ignore_malloc_size_of = "defined in webxr-api"]
id: InputId,
}

impl FakeXRInputController {
pub fn new_inherited(sender: IpcSender<MockDeviceMsg>, id: InputId) -> FakeXRInputController {
FakeXRInputController {
reflector: Reflector::new(),
sender,
id,
}
}

pub fn new(
global: &GlobalScope,
sender: IpcSender<MockDeviceMsg>,
id: InputId,
) -> DomRoot<FakeXRInputController> {
reflect_dom_object(
Box::new(FakeXRInputController::new_inherited(sender, id)),
global,
FakeXRInputControllerBinding::Wrap,
)
}

fn send_message(&self, msg: MockInputMsg) {
let _ = self
.sender
.send(MockDeviceMsg::MessageInputSource(self.id, msg));
}
}

impl FakeXRInputControllerMethods for FakeXRInputController {
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-setpointerorigin
fn SetPointerOrigin(&self, origin: &FakeXRRigidTransformInit, _emulated: bool) -> Fallible<()> {
self.send_message(MockInputMsg::SetPointerOrigin(Some(get_origin(origin)?)));
Ok(())
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-setgriporigin
fn SetGripOrigin(&self, origin: &FakeXRRigidTransformInit, _emulated: bool) -> Fallible<()> {
self.send_message(MockInputMsg::SetGripOrigin(Some(get_origin(origin)?)));
Ok(())
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-cleargriporigin
fn ClearGripOrigin(&self) {
self.send_message(MockInputMsg::SetGripOrigin(None))
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-disconnect
fn Disconnect(&self) {
self.send_message(MockInputMsg::Disconnect)
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-reconnect
fn Reconnect(&self) {
self.send_message(MockInputMsg::Reconnect)
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-startselection
fn StartSelection(&self) {
self.send_message(MockInputMsg::TriggerSelect(
SelectKind::Select,
SelectEvent::Start,
))
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-endselection
fn EndSelection(&self) {
self.send_message(MockInputMsg::TriggerSelect(
SelectKind::Select,
SelectEvent::End,
))
}

/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-simulateselect
fn SimulateSelect(&self) {
self.send_message(MockInputMsg::TriggerSelect(
SelectKind::Select,
SelectEvent::Select,
))
}
}
2 changes: 2 additions & 0 deletions components/script/dom/mod.rs
Expand Up @@ -301,6 +301,7 @@ pub mod eventtarget;
pub mod extendableevent;
pub mod extendablemessageevent;
pub mod fakexrdevice;
pub mod fakexrinputcontroller;
pub mod file;
pub mod filelist;
pub mod filereader;
Expand Down Expand Up @@ -564,6 +565,7 @@ pub mod xrframe;
pub mod xrinputsource;
pub mod xrinputsourcearray;
pub mod xrinputsourceevent;
pub mod xrinputsourceschangeevent;
pub mod xrpose;
pub mod xrreferencespace;
pub mod xrrenderstate;
Expand Down
11 changes: 2 additions & 9 deletions components/script/dom/webidls/FakeXRDevice.webidl
Expand Up @@ -10,25 +10,18 @@ interface FakeXRDevice {
// requestAnimationFrame() callbacks.
[Throws] void setViews(sequence<FakeXRViewInit> views);

// // behaves as if device was disconnected
// Promise<void> disconnect();

[Throws] void setViewerOrigin(FakeXRRigidTransformInit origin, optional boolean emulatedPosition = false);
void clearViewerOrigin();

[Throws] void setFloorOrigin(FakeXRRigidTransformInit origin);
void clearFloorOrigin();

// // Simulates devices focusing and blurring sessions.
// void simulateVisibilityChange(XRVisibilityState);
void simulateVisibilityChange(XRVisibilityState state);

// void setBoundsGeometry(sequence<FakeXRBoundsPoint> boundsCoodinates);
// // Sets eye level used for calculating floor-level spaces
// void setEyeLevel(float eyeLevel);


// Promise<FakeXRInputController>
// simulateInputSourceConnection(FakeXRInputSourceInit);
[Throws] FakeXRInputController simulateInputSourceConnection(FakeXRInputSourceInit init);

// behaves as if device was disconnected
Promise<void> disconnect();
Expand Down
53 changes: 53 additions & 0 deletions components/script/dom/webidls/FakeXRInputController.webidl
@@ -0,0 +1,53 @@
/* 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-test-api/#fakexrinputcontroller

[Exposed=Window, Pref="dom.webxr.test"]
interface FakeXRInputController {
// void setHandedness(XRHandedness handedness);
// void setTargetRayMode(XRTargetRayMode targetRayMode);
// void setProfiles(sequence<DOMString> profiles);
[Throws] void setGripOrigin(FakeXRRigidTransformInit gripOrigin, optional boolean emulatedPosition = false);
void clearGripOrigin();
[Throws] void setPointerOrigin(FakeXRRigidTransformInit pointerOrigin, optional boolean emulatedPosition = false);

void disconnect();
void reconnect();

void startSelection();
void endSelection();
void simulateSelect();

// void setSupportedButtons(sequence<FakeXRButtonStateInit> supportedButtons);
// void updateButtonState(FakeXRButtonStateInit buttonState);
};

dictionary FakeXRInputSourceInit {
required XRHandedness handedness;
required XRTargetRayMode targetRayMode;
required FakeXRRigidTransformInit pointerOrigin;
required sequence<DOMString> profiles;
boolean selectionStarted = false;
boolean selectionClicked = false;
sequence<FakeXRButtonStateInit> supportedButtons;
FakeXRRigidTransformInit gripOrigin;
};

enum FakeXRButtonType {
"grip",
"touchpad",
"thumbstick",
"optional-button",
"optional-thumbstick"
};

dictionary FakeXRButtonStateInit {
required FakeXRButtonType buttonType;
required boolean pressed;
required boolean touched;
required float pressedValue;
float xValue = 0.0;
float yValue = 0.0;
};
2 changes: 1 addition & 1 deletion components/script/dom/webidls/XRInputSource.webidl
Expand Up @@ -19,7 +19,7 @@ enum XRTargetRayMode {
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
interface XRInputSource {
readonly attribute XRHandedness handedness;
// [SameObject] readonly attribute XRTargetRayMode targetRayMode;
readonly attribute XRTargetRayMode targetRayMode;
[SameObject] readonly attribute XRSpace targetRaySpace;
[SameObject] readonly attribute XRSpace? gripSpace;
// [SameObject] readonly attribute Gamepad? gamepad;
Expand Down

0 comments on commit dbee7f7

Please sign in to comment.