Skip to content
This repository was archived by the owner on Feb 16, 2025. It is now read-only.

Commit ed1ec1a

Browse files
author
bors-servo
authored
Auto merge of #118 - Manishearth:inputs, r=asajeffrey
Expose TriggerSelect, properly handle input removal/adding Needed for input mocking. I'm working on the actual servo-side input mocking stuff as well as hit test mocking, but I thought I'd land this first. r? @asajeffrey or @jdm
2 parents c6abf4c + dc2c560 commit ed1ec1a

2 files changed

Lines changed: 100 additions & 36 deletions

File tree

webxr-api/mock.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ use crate::LeftEye;
1414
use crate::Native;
1515
use crate::Receiver;
1616
use crate::RightEye;
17+
use crate::SelectEvent;
18+
use crate::SelectKind;
1719
use crate::Sender;
1820
use crate::TargetRayMode;
1921
use crate::Viewer;
2022
use crate::Viewport;
23+
use crate::Visibility;
2124

2225
use euclid::{Rect, RigidTransform3D, Transform3D};
2326

@@ -68,8 +71,7 @@ pub enum MockDeviceMsg {
6871
SetViews(MockViewsInit),
6972
AddInputSource(MockInputInit),
7073
MessageInputSource(InputId, MockInputMsg),
71-
Focus,
72-
Blur,
74+
VisibilityChange(Visibility),
7375
Disconnect(Sender<()>),
7476
}
7577

@@ -88,6 +90,10 @@ pub enum MockInputMsg {
8890
SetTargetRayMode(TargetRayMode),
8991
SetPointerOrigin(Option<RigidTransform3D<f32, Input, Native>>),
9092
SetGripOrigin(Option<RigidTransform3D<f32, Input, Native>>),
93+
/// Note: SelectEvent::Select here refers to a complete Select event,
94+
/// not just the end event, i.e. it refers to
95+
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-simulateselect
96+
TriggerSelect(SelectKind, SelectEvent),
9197
Disconnect,
9298
Reconnect,
9399
}

webxr/headless/mod.rs

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use webxr_api::MockViewsInit;
2626
use webxr_api::Native;
2727
use webxr_api::Quitter;
2828
use webxr_api::Receiver;
29+
use webxr_api::SelectEvent;
2930
use webxr_api::Sender;
3031
use webxr_api::Session;
3132
use webxr_api::SessionMode;
@@ -52,6 +53,7 @@ struct InputInfo {
5253
active: bool,
5354
pointer: Option<RigidTransform3D<f32, Input, Native>>,
5455
grip: Option<RigidTransform3D<f32, Input, Native>>,
56+
clicking: bool,
5557
}
5658

5759
struct HeadlessDevice {
@@ -170,41 +172,22 @@ impl DeviceAPI<Surface> for HeadlessDevice {
170172

171173
fn wait_for_animation_frame(&mut self) -> Option<Frame> {
172174
thread::sleep(std::time::Duration::from_millis(20));
173-
let time_ns = time::precise_time_ns();
174175
let mut data = self.data.lock().unwrap();
175-
let transform = data.viewer_origin;
176-
let inputs = data
177-
.inputs
178-
.iter()
179-
.filter(|i| i.active)
180-
.map(|i| InputFrame {
181-
id: i.source.id,
182-
target_ray_origin: i.pointer,
183-
grip_origin: i.grip,
184-
pressed: false,
185-
squeezed: false,
186-
})
187-
.collect();
188-
189-
let mut events = if data.needs_view_update {
176+
let mut frame = data.get_frame();
177+
if data.needs_view_update {
190178
data.needs_view_update = false;
191-
vec![FrameUpdateEvent::UpdateViews(self.views())]
192-
} else {
193-
vec![]
179+
frame
180+
.events
181+
.push(FrameUpdateEvent::UpdateViews(self.views()))
194182
};
195183

196184
if data.needs_floor_update {
197-
events.push(FrameUpdateEvent::UpdateFloorTransform(
185+
frame.events.push(FrameUpdateEvent::UpdateFloorTransform(
198186
data.floor_transform.clone(),
199187
));
200188
data.needs_floor_update = false;
201189
}
202-
Some(Frame {
203-
transform,
204-
inputs,
205-
events,
206-
time_ns,
207-
})
190+
Some(frame)
208191
}
209192

210193
fn render_animation_frame(&mut self, surface: Surface) -> Surface {
@@ -240,6 +223,30 @@ impl HeadlessMockDiscovery {
240223
}
241224

242225
impl HeadlessDeviceData {
226+
fn get_frame(&self) -> Frame {
227+
let time_ns = time::precise_time_ns();
228+
let transform = self.viewer_origin;
229+
let inputs = self
230+
.inputs
231+
.iter()
232+
.filter(|i| i.active)
233+
.map(|i| InputFrame {
234+
id: i.source.id,
235+
target_ray_origin: i.pointer,
236+
grip_origin: i.grip,
237+
pressed: false,
238+
squeezed: false,
239+
})
240+
.collect();
241+
242+
Frame {
243+
transform,
244+
inputs,
245+
events: vec![],
246+
time_ns,
247+
}
248+
}
249+
243250
fn handle_msg(&mut self, msg: MockDeviceMsg) -> bool {
244251
match msg {
245252
MockDeviceMsg::SetViewerOrigin(viewer_origin) => {
@@ -253,18 +260,14 @@ impl HeadlessDeviceData {
253260
self.views = views;
254261
self.needs_view_update = true;
255262
}
256-
MockDeviceMsg::Focus => {
257-
// TODO
258-
}
259-
MockDeviceMsg::Blur => {
260-
// TODO
261-
}
263+
MockDeviceMsg::VisibilityChange(v) => self.events.callback(Event::VisibilityChange(v)),
262264
MockDeviceMsg::AddInputSource(init) => {
263265
self.inputs.push(InputInfo {
264266
source: init.source,
265267
pointer: init.pointer_origin,
266268
grip: init.grip_origin,
267269
active: true,
270+
clicking: false,
268271
});
269272
self.events.callback(Event::AddInput(init.source))
270273
}
@@ -275,8 +278,63 @@ impl HeadlessDeviceData {
275278
MockInputMsg::SetTargetRayMode(t) => input.source.target_ray_mode = t,
276279
MockInputMsg::SetPointerOrigin(p) => input.pointer = p,
277280
MockInputMsg::SetGripOrigin(p) => input.grip = p,
278-
MockInputMsg::Disconnect => input.active = false,
279-
MockInputMsg::Reconnect => input.active = true,
281+
MockInputMsg::TriggerSelect(kind, event) => {
282+
if !input.active {
283+
return true;
284+
}
285+
let clicking = input.clicking;
286+
input.clicking = event == SelectEvent::Start;
287+
let frame = self.get_frame();
288+
match event {
289+
SelectEvent::Start => {
290+
self.events.callback(Event::Select(id, kind, event, frame));
291+
}
292+
SelectEvent::End => {
293+
if clicking {
294+
self.events.callback(Event::Select(
295+
id,
296+
kind,
297+
SelectEvent::Select,
298+
frame,
299+
));
300+
} else {
301+
self.events.callback(Event::Select(
302+
id,
303+
kind,
304+
SelectEvent::End,
305+
frame,
306+
));
307+
}
308+
}
309+
SelectEvent::Select => {
310+
self.events.callback(Event::Select(
311+
id,
312+
kind,
313+
SelectEvent::Start,
314+
frame.clone(),
315+
));
316+
self.events.callback(Event::Select(
317+
id,
318+
kind,
319+
SelectEvent::Select,
320+
frame,
321+
));
322+
}
323+
}
324+
}
325+
MockInputMsg::Disconnect => {
326+
if input.active {
327+
self.events.callback(Event::RemoveInput(input.source.id));
328+
input.active = false;
329+
input.clicking = false;
330+
}
331+
}
332+
MockInputMsg::Reconnect => {
333+
if !input.active {
334+
self.events.callback(Event::AddInput(input.source));
335+
input.active = true;
336+
}
337+
}
280338
}
281339
}
282340
}

0 commit comments

Comments
 (0)