Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/openxr_data.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
clientcore::{Injected, Injector},
graphics_backends::{GraphicsBackend, VulkanData, supported_apis_enum},
system::System,
};
use derive_more::Deref;
use glam::f32::{Quat, Vec3};
use log::{info, warn};
use log::{debug, info, warn};
use openvr as vr;
use openxr as xr;
use std::mem::ManuallyDrop;
Expand Down Expand Up @@ -47,6 +48,7 @@ pub struct OpenXrData<C: Compositor> {
/// should only be externally accessed for testing
pub(crate) input: Injected<crate::input::Input<C>>,
pub(crate) compositor: Injected<C>,
pub(crate) system: Injected<System>,
}

impl<C: Compositor> Drop for OpenXrData<C> {
Expand Down Expand Up @@ -187,6 +189,7 @@ impl<C: Compositor> OpenXrData<C> {
enabled_extensions: exts,
input: injector.inject(),
compositor: injector.inject(),
system: injector.inject(),
})
}

Expand All @@ -206,6 +209,25 @@ impl<C: Compositor> OpenXrData<C> {
xr::Event::SessionStateChanged(event) => {
state = Some(event.state());
info!("OpenXR session state changed: {:?}", event.state());
if let Some(system) = self.system.get().filter(|_| {
(cfg!(test) || session_data.temp_vulkan.is_none())
&& state == Some(xr::SessionState::STOPPING)
}) {
debug!("pushing Quit event");
system.push_event(vr::VREvent_t {
eventType: vr::EVREventType::Quit as u32,
trackedDeviceIndex: vr::k_unTrackedDeviceIndexInvalid,
eventAgeSeconds: 0.0,
data: vr::VREvent_Data_t {
process: vr::VREvent_Process_t {
pid: u32::MAX,
oldPid: u32::MAX,
bForced: false,
bConnectionLost: false,
},
},
});
}
}
xr::Event::InteractionProfileChanged(_) => {
if let Some(input) = self.input.get() {
Expand Down
96 changes: 75 additions & 21 deletions src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use glam::{Mat3, Quat, Vec3};
use log::{debug, error, trace, warn};
use openvr as vr;
use openxr as xr;
use std::collections::VecDeque;
use std::ffi::{CStr, CString};
use std::sync::{Arc, Mutex};

Expand Down Expand Up @@ -152,6 +153,7 @@ impl ViewCache {
#[versions(023, 022, 021, 020, 019, 017, 016, 015, 014, 012, 011, 009)]
pub struct System {
openxr: Arc<RealOpenXrData>, // We don't need to test session restarting.
events: Mutex<VecDeque<vr::VREvent_t>>,
input: Injected<Input<crate::compositor::Compositor>>,
overlay: Injected<OverlayMan>,
vtables: Vtables,
Expand All @@ -166,6 +168,7 @@ impl System {
pub fn new(openxr: Arc<RealOpenXrData>, injector: &Injector) -> Self {
Self {
openxr,
events: Mutex::default(),
input: injector.inject(),
overlay: injector.inject(),
vtables: Default::default(),
Expand All @@ -192,6 +195,11 @@ impl System {
let mut views = self.views.lock().unwrap();
views.get_views(&session, self.openxr.display_time.get(), ty)
}

pub fn push_event(&self, event: vr::VREvent_t) {
let mut events = self.events.lock().unwrap();
events.push_back(event);
}
}

impl vr::IVRSystem023_Interface for System {
Expand Down Expand Up @@ -301,9 +309,7 @@ impl vr::IVRSystem023_Interface for System {
fn GetAppContainerFilePaths(&self, _: *mut std::os::raw::c_char, _: u32) -> u32 {
todo!()
}
fn AcknowledgeQuit_Exiting(&self) {
todo!()
}
fn AcknowledgeQuit_Exiting(&self) {}
fn PerformFirmwareUpdate(&self, _: vr::TrackedDeviceIndex_t) -> vr::EVRFirmwareError {
todo!()
}
Expand Down Expand Up @@ -483,6 +489,31 @@ impl vr::IVRSystem023_Interface for System {
size: u32,
pose: *mut vr::TrackedDevicePose_t,
) -> bool {
if let Some(queued) = self.events.lock().unwrap().pop_front() {
unsafe {
(&raw mut (*event).eventType).write(queued.eventType);
(&raw mut (*event).eventAgeSeconds).write(queued.eventAgeSeconds);
match vr::EVREventType::try_from(queued.eventType).unwrap() {
vr::EVREventType::Quit => {
const CONNECTION_LOST_OFFSET: usize =
std::mem::offset_of!(vr::VREvent_t, data)
+ std::mem::offset_of!(vr::VREvent_Process_t, bConnectionLost);

(&raw mut (*event).data.process.pid).write(queued.data.process.pid);
(&raw mut (*event).data.process.oldPid).write(queued.data.process.oldPid);
(&raw mut (*event).data.process.bForced).write(queued.data.process.bForced);
if size > CONNECTION_LOST_OFFSET as u32 {
(&raw mut (*event).data.process.bConnectionLost)
.write(queued.data.process.bConnectionLost);
}

return true;
}
_ => todo!(),
}
}
Comment thread
ImSapphire marked this conversation as resolved.
}

let Some(input) = self.input.get() else {
return false;
};
Expand Down Expand Up @@ -974,32 +1005,35 @@ impl vr::IVRSystem009On011 for System {
self,
origin,
&mut e,
std::mem::size_of_val(&event) as u32,
std::mem::size_of_val(&e) as u32,
pose,
);

if ret && !event.is_null() {
let event = unsafe { event.as_mut() }.unwrap();
event.eventType = if let Ok(t) = vr::EVREventType::try_from(e.eventType) {
t
} else {
let Ok(event_type) = vr::EVREventType::try_from(e.eventType) else {
error!("Unhandled event type for 0.9.12: {}", e.eventType);
return false;
};
event.trackedDeviceIndex = e.trackedDeviceIndex;
event.data = match e.eventType {
x if x == vr::EVREventType::ButtonPress as u32
|| x == vr::EVREventType::ButtonUnpress as u32
|| x == vr::EVREventType::ButtonTouch as u32
|| x == vr::EVREventType::ButtonUntouch as u32 =>
{
vr::vr_0_9_12::VREvent_Data_t {
controller: unsafe { e.data.controller },

unsafe {
(&raw mut (*event).eventType).write(event_type);
(&raw mut (*event).trackedDeviceIndex).write(e.trackedDeviceIndex);
match event_type {
vr::EVREventType::ButtonPress
| vr::EVREventType::ButtonUnpress
| vr::EVREventType::ButtonTouch
| vr::EVREventType::ButtonUntouch => {
(&raw mut (*event).data.controller).write(e.data.controller);
}
vr::EVREventType::Quit => {
(&raw mut (*event).data.process.pid).write(e.data.process.pid);
(&raw mut (*event).data.process.oldPid).write(e.data.process.oldPid);
(&raw mut (*event).data.process.bForced).write(e.data.process.bForced);
}
other => {
error!("Unhandled event type data for 0.9.12: {other:?}");
return false;
}
}
other => {
error!("Unhandled event type data for 0.9.12: {other:?}");
return false;
}
}
}
Expand Down Expand Up @@ -1056,4 +1090,24 @@ mod tests {
test_prop(vr::ETrackedDeviceProperty::ManufacturerName_String);
test_prop(vr::ETrackedDeviceProperty::ControllerType_String);
}

#[test]
fn test_session_stop() {
let xr = Arc::new(OpenXrData::new(&Injector::default()).unwrap());
let injector = Injector::default();
let system = Arc::new(System::new(xr.clone(), &injector));

xr.system.set(Arc::downgrade(&system));

xr.session_data.get().session.request_exit().unwrap();
xr.poll_events();
let mut event = vr::VREvent_t::default();
assert!(system.PollNextEventWithPose(
vr::ETrackingUniverseOrigin::Standing,
&mut event,
std::mem::size_of_val(&event) as u32,
std::ptr::null_mut()
));
assert_eq!(event.eventType, vr::EVREventType::Quit as u32);
}
}
Loading