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