servoshell/desktop/
webxr.rs1use std::cell::RefCell;
6use std::rc::Rc;
7use std::sync::Arc;
8use std::sync::atomic::{AtomicBool, Ordering};
9
10use servo::webxr::{GlWindowDiscovery, WebXrRegistry};
11#[cfg(target_os = "windows")]
12use servo::webxr::{OpenXrAppInfo, OpenXrDiscovery};
13use servo::{Preferences, pref, prefs};
14use winit::event_loop::ActiveEventLoop;
15
16use crate::window::PlatformWindow;
17
18enum XrDiscovery {
19 GlWindow(GlWindowDiscovery),
20 #[cfg(target_os = "windows")]
21 OpenXr(OpenXrDiscovery),
22}
23
24pub(crate) struct XrDiscoveryWebXrRegistry {
25 xr_discovery: RefCell<Option<XrDiscovery>>,
26}
27
28impl XrDiscoveryWebXrRegistry {
29 pub(crate) fn new_boxed(
30 window: Rc<dyn PlatformWindow>,
31 event_loop: Option<&ActiveEventLoop>,
32 preferences: &Preferences,
33 ) -> Box<Self> {
34 let Some(event_loop) = event_loop else {
35 return Box::new(Self {
36 xr_discovery: RefCell::new(None),
37 });
38 };
39
40 let xr_discovery = if preferences.dom_webxr_openxr_enabled {
41 #[cfg(target_os = "windows")]
42 {
43 let app_info = OpenXrAppInfo::new("Servoshell", 0, "Servo", 0);
44 Some(XrDiscovery::OpenXr(OpenXrDiscovery::new(None, app_info)))
45 }
46 #[cfg(not(target_os = "windows"))]
47 None
48 } else if preferences.dom_webxr_glwindow_enabled {
49 let window = window.new_glwindow(event_loop);
50 Some(XrDiscovery::GlWindow(GlWindowDiscovery::new(window)))
51 } else {
52 None
53 };
54
55 Box::new(Self {
56 xr_discovery: RefCell::new(xr_discovery),
57 })
58 }
59}
60
61struct XrPrefObserver(Arc<AtomicBool>);
62
63impl prefs::PreferencesObserver for XrPrefObserver {
64 fn prefs_changed(&self, changes: &[(&'static str, prefs::PrefValue)]) {
65 if let Some((_, value)) = changes.iter().find(|(name, _)| *name == "dom_webxr_test") {
66 let prefs::PrefValue::Bool(value) = value else {
67 return;
68 };
69 self.0.store(*value, Ordering::Relaxed);
70 }
71 }
72}
73
74impl WebXrRegistry for XrDiscoveryWebXrRegistry {
75 fn register(&self, xr: &mut servo::webxr::MainThreadRegistry) {
76 use servo::webxr::HeadlessMockDiscovery;
77
78 let mock_enabled = Arc::new(AtomicBool::new(pref!(dom_webxr_test)));
79 xr.register_mock(HeadlessMockDiscovery::new(mock_enabled.clone()));
80 prefs::add_observer(Box::new(XrPrefObserver(mock_enabled)));
81
82 if let Some(xr_discovery) = self.xr_discovery.take() {
83 match xr_discovery {
84 XrDiscovery::GlWindow(discovery) => xr.register(discovery),
85 #[cfg(target_os = "windows")]
86 XrDiscovery::OpenXr(discovery) => xr.register(discovery),
87 }
88 }
89 }
90}