improve error handling

This commit is contained in:
galister
2024-02-18 22:24:36 +01:00
parent 615470aa92
commit 63b43c0e59
17 changed files with 517 additions and 611 deletions

64
Cargo.lock generated
View File

@@ -212,7 +212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener 5.0.0", "event-listener 5.1.0",
"event-listener-strategy 0.5.0", "event-listener-strategy 0.5.0",
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@@ -287,7 +287,7 @@ dependencies = [
"futures-io", "futures-io",
"futures-lite 2.2.0", "futures-lite 2.2.0",
"parking", "parking",
"polling 3.4.0", "polling 3.5.0",
"rustix 0.38.31", "rustix 0.38.31",
"slab", "slab",
"tracing", "tracing",
@@ -454,7 +454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955e602d2d68b79ca5d674984259234fad2c8d869ad99011699e0a3cd76f38cd" checksum = "955e602d2d68b79ca5d674984259234fad2c8d869ad99011699e0a3cd76f38cd"
dependencies = [ dependencies = [
"autocxx-engine", "autocxx-engine",
"env_logger 0.9.3", "env_logger",
"indexmap 1.9.3", "indexmap 1.9.3",
"syn 2.0.49", "syn 2.0.49",
] ]
@@ -682,7 +682,7 @@ checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.4.2",
"log", "log",
"polling 3.4.0", "polling 3.5.0",
"rustix 0.38.31", "rustix 0.38.31",
"slab", "slab",
"thiserror", "thiserror",
@@ -1252,19 +1252,6 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@@ -1311,9 +1298,9 @@ dependencies = [
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "5.0.0" version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b72557800024fabbaa2449dd4bf24e37b93702d457a4d4f2b0dd1f0f039f20c1" checksum = "b7ad6fd685ce13acd6d9541a30f6db6567a7a24c9ffd4ba2955d29e3f22c8b27"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"parking", "parking",
@@ -1336,7 +1323,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291"
dependencies = [ dependencies = [
"event-listener 5.0.0", "event-listener 5.1.0",
"pin-project-lite", "pin-project-lite",
] ]
@@ -1380,6 +1367,22 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "flexi_logger"
version = "0.27.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469e584c031833564840fb0cdbce99bdfe946fd45480a188545e73a76f45461c"
dependencies = [
"chrono",
"glob",
"is-terminal",
"lazy_static",
"log",
"nu-ansi-term",
"regex",
"thiserror",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@@ -2304,6 +2307,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.49.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68"
dependencies = [
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@@ -2470,7 +2482,7 @@ dependencies = [
[[package]] [[package]]
name = "ovr_overlay" name = "ovr_overlay"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/galister/ovr_overlay_oyasumi#0fe2e5412840f4df2def8eec6e342f220e03135e" source = "git+https://github.com/galister/ovr_overlay_oyasumi#4a1711248c1a0d57ad8e3266726c3407ee30418e"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"derive_more", "derive_more",
@@ -2485,7 +2497,7 @@ dependencies = [
[[package]] [[package]]
name = "ovr_overlay_sys" name = "ovr_overlay_sys"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/galister/ovr_overlay_oyasumi#0fe2e5412840f4df2def8eec6e342f220e03135e" source = "git+https://github.com/galister/ovr_overlay_oyasumi#4a1711248c1a0d57ad8e3266726c3407ee30418e"
dependencies = [ dependencies = [
"autocxx", "autocxx",
"autocxx-build", "autocxx-build",
@@ -2678,9 +2690,9 @@ dependencies = [
[[package]] [[package]]
name = "polling" name = "polling"
version = "3.4.0" version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"concurrent-queue", "concurrent-queue",
@@ -2976,7 +2988,7 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]] [[package]]
name = "rxscreen" name = "rxscreen"
version = "0.1.6" version = "0.1.6"
source = "git+https://github.com/galister/rxscreen.git#1d0eb4f66c0cd5f1ddfc7ee2bab930019cb9e0d5" source = "git+https://github.com/galister/rxscreen.git#bb045fbe830d7ff4d2d5ffc408f3df8944e7d90f"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -4308,7 +4320,7 @@ dependencies = [
"chrono-tz", "chrono-tz",
"cstr", "cstr",
"ctrlc", "ctrlc",
"env_logger 0.10.2", "flexi_logger",
"fontconfig-rs", "fontconfig-rs",
"freetype-rs", "freetype-rs",
"futures", "futures",

View File

@@ -17,7 +17,7 @@ chrono = "0.4.29"
chrono-tz = "0.8.5" chrono-tz = "0.8.5"
cstr = "0.2.11" cstr = "0.2.11"
ctrlc = { version = "3.4.2", features = ["termination"] } ctrlc = { version = "3.4.2", features = ["termination"] }
env_logger = "0.10.0" flexi_logger = "0.27.4"
fontconfig-rs = "0.1.1" fontconfig-rs = "0.1.1"
freetype-rs = "0.32.0" freetype-rs = "0.32.0"
futures = "0.3.29" futures = "0.3.29"

View File

@@ -6,6 +6,8 @@ use std::{
use glam::{Affine3A, Vec2, Vec3A}; use glam::{Affine3A, Vec2, Vec3A};
use idmap::IdMap; use idmap::IdMap;
use openxr as xr;
use thiserror::Error;
use crate::{ use crate::{
overlays::{ overlays::{
@@ -18,11 +20,19 @@ use crate::{
use super::overlay::{OverlayData, OverlayState}; use super::overlay::{OverlayData, OverlayState};
#[derive(Error, Debug)]
pub enum BackendError { pub enum BackendError {
#[error("backend not supported")]
NotSupported, NotSupported,
#[cfg(feature = "openxr")]
#[error("openxr error {0}")]
OpenXrError(#[from] xr::sys::Result),
#[error("shutdown")]
Shutdown, Shutdown,
#[error("restart")]
Restart, Restart,
Fatal, #[error("fatal")]
Fatal(#[from] anyhow::Error),
} }
pub struct OverlayContainer<T> pub struct OverlayContainer<T>
@@ -191,6 +201,7 @@ impl TaskContainer {
break; break;
} }
// Safe unwrap because we peeked.
dest_buf.push_back(self.tasks.pop().unwrap().task); dest_buf.push_back(self.tasks.pop().unwrap().task);
} }
} }

View File

@@ -395,10 +395,10 @@ impl Pointer {
} }
} }
hits.sort_by(|a, b| a.dist.partial_cmp(&b.dist).unwrap()); hits.sort_by(|a, b| a.dist.total_cmp(&b.dist));
for hit in hits.iter() { for hit in hits.iter() {
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // this is safe let overlay = overlays.get_by_id(hit.overlay).unwrap(); // safe because we just got the id from the overlay
let uv = overlay let uv = overlay
.state .state
@@ -447,27 +447,32 @@ impl Pointer {
O: Default, O: Default,
{ {
if self.now.grab { if self.now.grab {
let grab_data = self.interaction.grabbed.as_mut().unwrap(); if let Some(grab_data) = self.interaction.grabbed.as_mut() {
if self.now.click { if self.now.click {
self.interaction.mode = PointerMode::Special; self.interaction.mode = PointerMode::Special;
let cur_scale = overlay.state.transform.x_axis.length(); let cur_scale = overlay.state.transform.x_axis.length();
if cur_scale < 0.1 && self.now.scroll > 0.0 { if cur_scale < 0.1 && self.now.scroll > 0.0 {
return; return;
} else if cur_scale > 20. && self.now.scroll < 0.0 { }
return; if cur_scale > 20. && self.now.scroll < 0.0 {
} return;
}
overlay.state.transform.matrix3 = overlay overlay.state.transform.matrix3 = overlay
.state .state
.transform .transform
.matrix3 .matrix3
.mul_scalar(1.0 - 0.025 * self.now.scroll); .mul_scalar(1.0 - 0.025 * self.now.scroll);
} else {
grab_data.offset.z -= self.now.scroll * 0.05;
}
overlay.state.transform.translation = self.pose.transform_point3a(grab_data.offset);
overlay.state.realign(hmd);
overlay.state.dirty = true;
} else { } else {
grab_data.offset.z -= self.now.scroll * 0.05; log::error!("Grabbed overlay {} does not exist", overlay.state.id);
self.interaction.grabbed = None;
} }
overlay.state.transform.translation = self.pose.transform_point3a(grab_data.offset);
overlay.state.realign(hmd);
overlay.state.dirty = true;
} else { } else {
overlay.state.saved_point = Some( overlay.state.saved_point = Some(
hmd.inverse() hmd.inverse()

View File

@@ -1,5 +1,8 @@
use glam::Affine3A; use glam::Affine3A;
use ovr_overlay::{pose::Matrix3x4, sys::HmdMatrix34_t}; use ovr_overlay::{pose::Matrix3x4, sys::HmdMatrix34_t};
use thiserror::Error;
use crate::backend::common::BackendError;
pub trait Affine3AConvert { pub trait Affine3AConvert {
fn from_affine(affine: Affine3A) -> Self; fn from_affine(affine: Affine3A) -> Self;
@@ -75,3 +78,21 @@ impl Affine3AConvert for HmdMatrix34_t {
]) ])
} }
} }
#[derive(Error, Debug)]
pub(super) enum OVRError {
#[error("ovr input error: {0}")]
InputError(&'static str),
}
impl From<ovr_overlay::errors::EVRInputError> for OVRError {
fn from(e: ovr_overlay::errors::EVRInputError) -> Self {
OVRError::InputError(e.description())
}
}
impl From<OVRError> for BackendError {
fn from(e: OVRError) -> Self {
BackendError::Fatal(anyhow::Error::new(e))
}
}

View File

@@ -17,16 +17,7 @@ use crate::{
state::AppState, state::AppState,
}; };
use super::helpers::Affine3AConvert; use super::helpers::{Affine3AConvert, OVRError};
macro_rules! result_str {
( $e:expr ) => {
match $e {
Ok(x) => Ok(x),
Err(y) => Err(y.description()),
}
};
}
const SET_DEFAULT: &str = "/actions/default"; const SET_DEFAULT: &str = "/actions/default";
const INPUT_SOURCES: [&str; 2] = ["/user/hand/left", "/user/hand/right"]; const INPUT_SOURCES: [&str; 2] = ["/user/hand/left", "/user/hand/right"];
@@ -71,34 +62,32 @@ pub(super) struct OpenVrHandSource {
} }
impl OpenVrInputSource { impl OpenVrInputSource {
pub fn new(input: &mut InputManager) -> Result<Self, &'static str> { pub fn new(input: &mut InputManager) -> Result<Self, OVRError> {
let set_hnd = result_str!(input.get_action_set_handle(SET_DEFAULT))?; let set_hnd = input.get_action_set_handle(SET_DEFAULT)?;
let click_hnd = result_str!(input.get_action_handle(PATH_CLICK))?; let click_hnd = input.get_action_handle(PATH_CLICK)?;
let grab_hnd = result_str!(input.get_action_handle(PATH_GRAB))?; let grab_hnd = input.get_action_handle(PATH_GRAB)?;
let scroll_hnd = result_str!(input.get_action_handle(PATH_SCROLL))?; let scroll_hnd = input.get_action_handle(PATH_SCROLL)?;
let alt_click_hnd = result_str!(input.get_action_handle(PATH_ALT_CLICK))?; let alt_click_hnd = input.get_action_handle(PATH_ALT_CLICK)?;
let show_hide_hnd = result_str!(input.get_action_handle(PATH_SHOW_HIDE))?; let show_hide_hnd = input.get_action_handle(PATH_SHOW_HIDE)?;
let space_drag_hnd = result_str!(input.get_action_handle(PATH_SPACE_DRAG))?; let space_drag_hnd = input.get_action_handle(PATH_SPACE_DRAG)?;
let click_modifier_right_hnd = let click_modifier_right_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT)?;
result_str!(input.get_action_handle(PATH_CLICK_MODIFIER_RIGHT))?; let click_modifier_middle_hnd = input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE)?;
let click_modifier_middle_hnd =
result_str!(input.get_action_handle(PATH_CLICK_MODIFIER_MIDDLE))?;
let input_hnd: Vec<InputValueHandle> = INPUT_SOURCES let input_hnd: Vec<InputValueHandle> = INPUT_SOURCES
.iter() .iter()
.map(|path| Ok(result_str!(input.get_input_source_handle(path))?)) .map(|path| Ok((input.get_input_source_handle(path))?))
.collect::<Result<_, &'static str>>()?; .collect::<Result<_, OVRError>>()?;
let pose_hnd: Vec<ActionHandle> = PATH_POSES let pose_hnd: Vec<ActionHandle> = PATH_POSES
.iter() .iter()
.map(|path| Ok(result_str!(input.get_action_handle(path))?)) .map(|path| Ok((input.get_action_handle(path))?))
.collect::<Result<_, &'static str>>()?; .collect::<Result<_, OVRError>>()?;
let haptics_hnd: Vec<ActionHandle> = PATH_HAPTICS let haptics_hnd: Vec<ActionHandle> = PATH_HAPTICS
.iter() .iter()
.map(|path| Ok(result_str!(input.get_action_handle(path))?)) .map(|path| Ok((input.get_action_handle(path))?))
.collect::<Result<_, &'static str>>()?; .collect::<Result<_, OVRError>>()?;
let hands: [OpenVrHandSource; 2] = array::from_fn(|i| OpenVrHandSource { let hands: [OpenVrHandSource; 2] = array::from_fn(|i| OpenVrHandSource {
has_pose: false, has_pose: false,
@@ -317,38 +306,29 @@ pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
let action_path = CONFIG_ROOT_PATH.join("actions.json"); let action_path = CONFIG_ROOT_PATH.join("actions.json");
if !action_path.is_file() { if !action_path.is_file() {
File::create(&action_path) File::create(&action_path)?.write_all(include_bytes!("../../res/actions.json"))?;
.unwrap()
.write_all(include_bytes!("../../res/actions.json"))
.unwrap();
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path) File::create(&binding_path)?
.unwrap() .write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))
.unwrap();
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path) File::create(&binding_path)?
.unwrap() .write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
.write_all(include_bytes!("../../res/actions_binding_vive.json"))
.unwrap();
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json"); let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path) File::create(&binding_path)?
.unwrap() .write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))
.unwrap();
} }
if let Err(e) = input.set_action_manifest(action_path.as_path()) { if let Err(e) = input.set_action_manifest(action_path.as_path()) {
bail!("Failed to set action manifest: {}", e.description()); bail!("Failed to set action manifest: {}", e);
} }
Ok(()) Ok(())
} }

View File

@@ -7,6 +7,7 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use anyhow::{anyhow, Result};
use ovr_overlay::{ use ovr_overlay::{
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType}, sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
TrackedDeviceIndex, TrackedDeviceIndex,
@@ -83,7 +84,7 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let mut state = { let mut state = {
let graphics = WlxGraphics::new_openvr(instance_extensions, device_extensions_fn); let graphics = WlxGraphics::new_openvr(instance_extensions, device_extensions_fn);
AppState::from_graphics(graphics) AppState::from_graphics(graphics)?
}; };
install_manifest(&mut app_mgr); install_manifest(&mut app_mgr);
@@ -97,22 +98,17 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
state.hid_provider.set_desktop_extent(overlays.extent); state.hid_provider.set_desktop_extent(overlays.extent);
if let Err(e) = set_action_manifest(&mut input_mngr) { set_action_manifest(&mut input_mngr)?;
log::error!("{}", e.to_string());
return Err(BackendError::Fatal);
};
let Ok(mut input_source) = OpenVrInputSource::new(&mut input_mngr) else { let mut input_source = OpenVrInputSource::new(&mut input_mngr)?;
log::error!("Failed to initialize input");
return Err(BackendError::Fatal);
};
let Ok(refresh_rate) = system_mngr.get_tracked_device_property::<f32>( let Ok(refresh_rate) = system_mngr.get_tracked_device_property::<f32>(
TrackedDeviceIndex::HMD, TrackedDeviceIndex::HMD,
ETrackedDeviceProperty::Prop_DisplayFrequency_Float, ETrackedDeviceProperty::Prop_DisplayFrequency_Float,
) else { ) else {
log::error!("Failed to get display refresh rate"); return Err(BackendError::Fatal(anyhow!(
return Err(BackendError::Fatal); "Failed to get HMD refresh rate"
)));
}; };
log::info!("HMD running @ {} Hz", refresh_rate); log::info!("HMD running @ {} Hz", refresh_rate);

View File

@@ -92,7 +92,7 @@ impl OverlayData<OpenVrOverlayData> {
}; };
log::debug!("{}: show", self.state.name); log::debug!("{}: show", self.state.name);
if let Err(e) = overlay.set_visibility(handle, true) { if let Err(e) = overlay.set_visibility(handle, true) {
panic!("Failed to show overlay: {}", e); log::error!("{}: Failed to show overlay: {}", self.state.name, e);
} }
self.data.visible = true; self.data.visible = true;
self.backend.resume(app); self.backend.resume(app);
@@ -104,7 +104,7 @@ impl OverlayData<OpenVrOverlayData> {
}; };
log::debug!("{}: hide", self.state.name); log::debug!("{}: hide", self.state.name);
if let Err(e) = overlay.set_visibility(handle, false) { if let Err(e) = overlay.set_visibility(handle, false) {
panic!("Failed to hide overlay: {}", e); log::error!("{}: Failed to hide overlay: {}", self.state.name, e);
} }
self.data.visible = false; self.data.visible = false;
self.backend.pause(app); self.backend.pause(app);
@@ -116,7 +116,7 @@ impl OverlayData<OpenVrOverlayData> {
return; return;
}; };
if let Err(e) = overlay.set_opacity(handle, self.state.alpha) { if let Err(e) = overlay.set_opacity(handle, self.state.alpha) {
panic!("Failed to set overlay alpha: {}", e); log::error!("{}: Failed to set overlay alpha: {}", self.state.name, e);
} }
} }
@@ -134,7 +134,7 @@ impl OverlayData<OpenVrOverlayData> {
a: self.data.color.w, a: self.data.color.w,
}, },
) { ) {
panic!("Failed to set overlay tint: {}", e); log::error!("{}: Failed to set overlay tint: {}", self.state.name, e);
} }
} }
@@ -144,7 +144,7 @@ impl OverlayData<OpenVrOverlayData> {
return; return;
}; };
if let Err(e) = overlay.set_width(handle, self.data.width) { if let Err(e) = overlay.set_width(handle, self.data.width) {
panic!("Failed to set overlay width: {}", e); log::error!("{}: Failed to set overlay width: {}", self.state.name, e);
} }
} }
@@ -154,7 +154,11 @@ impl OverlayData<OpenVrOverlayData> {
return; return;
}; };
if let Err(e) = overlay.set_curvature(handle, self.data.curvature) { if let Err(e) = overlay.set_curvature(handle, self.data.curvature) {
panic!("Failed to set overlay curvature: {}", e); log::error!(
"{}: Failed to set overlay curvature: {}",
self.state.name,
e
);
} }
} }
@@ -164,7 +168,7 @@ impl OverlayData<OpenVrOverlayData> {
return; return;
}; };
if let Err(e) = overlay.set_sort_order(handle, self.data.sort_order) { if let Err(e) = overlay.set_sort_order(handle, self.data.sort_order) {
panic!("Failed to set overlay z order: {}", e); log::error!("{}: Failed to set overlay z order: {}", self.state.name, e);
} }
} }
@@ -181,7 +185,11 @@ impl OverlayData<OpenVrOverlayData> {
ETrackingUniverseOrigin::TrackingUniverseStanding, ETrackingUniverseOrigin::TrackingUniverseStanding,
&transform, &transform,
) { ) {
panic!("Failed to set overlay transform: {}", e); log::error!(
"{}: Failed to set overlay transform: {}",
self.state.name,
e
);
} }
} }
@@ -230,8 +238,7 @@ impl OverlayData<OpenVrOverlayData> {
image.usage() image.usage()
); );
if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) { if let Err(e) = overlay.set_image_vulkan(handle, &mut texture) {
panic!("Failed to set overlay texture: {}", e); log::error!("{}: Failed to set overlay texture: {}", self.state.name, e);
} }
log::debug!("{}: Uploaded texture", self.state.name);
} }
} }

View File

@@ -57,27 +57,26 @@ pub(super) struct OpenXrHandSource {
} }
impl OpenXrInputSource { impl OpenXrInputSource {
pub fn new(xr: &XrState) -> Self { pub fn new(xr: &XrState) -> Result<Self, xr::sys::Result> {
let mut action_set = xr let mut action_set =
.session xr.session
.instance() .instance()
.create_action_set("wlx-overlay-s", "WlxOverlay-S Actions", 0) .create_action_set("wlx-overlay-s", "WlxOverlay-S Actions", 0)?;
.expect("Failed to create action set");
let left_source = OpenXrHandSource::new(&mut action_set, "left"); let left_source = OpenXrHandSource::new(&mut action_set, "left")?;
let right_source = OpenXrHandSource::new(&mut action_set, "right"); let right_source = OpenXrHandSource::new(&mut action_set, "right")?;
suggest_bindings(&xr.instance, &[&left_source, &right_source]); suggest_bindings(&xr.instance, &[&left_source, &right_source])?;
xr.session.attach_action_sets(&[&action_set]).unwrap(); xr.session.attach_action_sets(&[&action_set])?;
Self { Ok(Self {
action_set, action_set,
hands: [ hands: [
OpenXrHand::new(&xr, left_source), OpenXrHand::new(&xr, left_source)?,
OpenXrHand::new(&xr, right_source), OpenXrHand::new(&xr, right_source)?,
], ],
} })
} }
pub fn haptics(&self, xr: &XrState, hand: usize, haptics: &Haptics) { pub fn haptics(&self, xr: &XrState, hand: usize, haptics: &Haptics) {
@@ -95,10 +94,8 @@ impl OpenXrInputSource {
); );
} }
pub fn update(&self, xr: &XrState, state: &mut AppState) { pub fn update(&self, xr: &XrState, state: &mut AppState) -> Result<(), xr::sys::Result> {
xr.session xr.session.sync_actions(&[(&self.action_set).into()])?;
.sync_actions(&[(&self.action_set).into()])
.unwrap();
for i in 0..2 { for i in 0..2 {
self.hands[i].update( self.hands[i].update(
@@ -106,19 +103,21 @@ impl OpenXrInputSource {
&xr.stage, &xr.stage,
&xr.session, &xr.session,
xr.predicted_display_time, xr.predicted_display_time,
); )?;
} }
Ok(())
} }
} }
impl OpenXrHand { impl OpenXrHand {
pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Self { pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Result<Self, xr::sys::Result> {
let space = source let space = source.action_pose.create_space(
.action_pose xr.session.clone(),
.create_space(xr.session.clone(), xr::Path::NULL, xr::Posef::IDENTITY) xr::Path::NULL,
.unwrap(); xr::Posef::IDENTITY,
)?;
Self { source, space } Ok(Self { source, space })
} }
pub(super) fn update( pub(super) fn update(
@@ -127,8 +126,8 @@ impl OpenXrHand {
stage: &xr::Space, stage: &xr::Space,
session: &XrSession, session: &XrSession,
time: xr::Time, time: xr::Time,
) { ) -> Result<(), xr::sys::Result> {
let location = self.space.locate(stage, time).unwrap(); let location = self.space.locate(stage, time)?;
if location if location
.location_flags .location_flags
.contains(xr::SpaceLocationFlags::ORIENTATION_VALID) .contains(xr::SpaceLocationFlags::ORIENTATION_VALID)
@@ -141,126 +140,103 @@ impl OpenXrHand {
pointer.now.click = self pointer.now.click = self
.source .source
.action_click .action_click
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state .current_state
> 0.7; > 0.7;
pointer.now.grab = self pointer.now.grab = self
.source .source
.action_grab .action_grab
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state .current_state
> 0.7; > 0.7;
pointer.now.scroll = self pointer.now.scroll = self
.source .source
.action_scroll .action_scroll
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state; .current_state;
pointer.now.alt_click = self pointer.now.alt_click = self
.source .source
.action_alt_click .action_alt_click
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state .current_state
> 0.7; > 0.7;
pointer.now.show_hide = self pointer.now.show_hide = self
.source .source
.action_show_hide .action_show_hide
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state; .current_state;
pointer.now.click_modifier_right = self pointer.now.click_modifier_right = self
.source .source
.action_click_modifier_right .action_click_modifier_right
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state; .current_state;
pointer.now.click_modifier_middle = self pointer.now.click_modifier_middle = self
.source .source
.action_click_modifier_middle .action_click_modifier_middle
.state(session, xr::Path::NULL) .state(session, xr::Path::NULL)?
.unwrap()
.current_state; .current_state;
Ok(())
} }
} }
// supported action types: Haptic, Posef, Vector2f, f32, bool // supported action types: Haptic, Posef, Vector2f, f32, bool
impl OpenXrHandSource { impl OpenXrHandSource {
pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> Self { pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> Result<Self, xr::sys::Result> {
let action_pose = action_set let action_pose = action_set.create_action::<xr::Posef>(
.create_action::<xr::Posef>( &format!("{}_hand", side),
&format!("{}_hand", side), &format!("{} hand pose", side),
&format!("{} hand pose", side), &[],
&[], )?;
)
.unwrap();
let action_click = action_set let action_click = action_set.create_action::<f32>(
.create_action::<f32>( &format!("{}_click", side),
&format!("{}_click", side), &format!("{} hand click", side),
&format!("{} hand click", side), &[],
&[], )?;
) let action_grab = action_set.create_action::<f32>(
.unwrap(); &format!("{}_grab", side),
let action_grab = action_set &format!("{} hand grab", side),
.create_action::<f32>( &[],
&format!("{}_grab", side), )?;
&format!("{} hand grab", side), let action_scroll = action_set.create_action::<f32>(
&[], &format!("{}_scroll", side),
) &format!("{} hand scroll", side),
.unwrap(); &[],
let action_scroll = action_set )?;
.create_action::<f32>( let action_alt_click = action_set.create_action::<f32>(
&format!("{}_scroll", side), &format!("{}_alt_click", side),
&format!("{} hand scroll", side), &format!("{} hand alt click", side),
&[], &[],
) )?;
.unwrap(); let action_show_hide = action_set.create_action::<bool>(
let action_alt_click = action_set &format!("{}_show_hide", side),
.create_action::<f32>( &format!("{} hand show/hide", side),
&format!("{}_alt_click", side), &[],
&format!("{} hand alt click", side), )?;
&[], let action_click_modifier_right = action_set.create_action::<bool>(
) &format!("{}_click_modifier_right", side),
.unwrap(); &format!("{} hand right click modifier", side),
let action_show_hide = action_set &[],
.create_action::<bool>( )?;
&format!("{}_show_hide", side), let action_click_modifier_middle = action_set.create_action::<bool>(
&format!("{} hand show/hide", side), &format!("{}_click_modifier_middle", side),
&[], &format!("{} hand middle click modifier", side),
) &[],
.unwrap(); )?;
let action_click_modifier_right = action_set let action_haptics = action_set.create_action::<xr::Haptic>(
.create_action::<bool>( &format!("{}_haptics", side),
&format!("{}_click_modifier_right", side), &format!("{} hand haptics", side),
&format!("{} hand right click modifier", side), &[],
&[], )?;
)
.unwrap();
let action_click_modifier_middle = action_set
.create_action::<bool>(
&format!("{}_click_modifier_middle", side),
&format!("{} hand middle click modifier", side),
&[],
)
.unwrap();
let action_haptics = action_set
.create_action::<xr::Haptic>(
&format!("{}_haptics", side),
&format!("{} hand haptics", side),
&[],
)
.unwrap();
Self { Ok(Self {
action_pose, action_pose,
action_click, action_click,
action_grab, action_grab,
@@ -270,354 +246,239 @@ impl OpenXrHandSource {
action_click_modifier_right, action_click_modifier_right,
action_click_modifier_middle, action_click_modifier_middle,
action_haptics, action_haptics,
} })
} }
} }
fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) { fn suggest_bindings(
let path = instance instance: &xr::Instance,
.string_to_path("/interaction_profiles/khr/simple_controller") hands: &[&OpenXrHandSource; 2],
.unwrap(); ) -> Result<(), xr::sys::Result> {
let path = instance.string_to_path("/interaction_profiles/khr/simple_controller")?;
// not fully functional, but helpful for debugging // not fully functional, but helpful for debugging
instance instance.suggest_interaction_profile_bindings(
.suggest_interaction_profile_bindings( path,
path, &[
&[ xr::Binding::new(
xr::Binding::new( &hands[0].action_pose,
&hands[0].action_pose, instance.string_to_path("/user/hand/left/input/aim/pose")?,
instance ),
.string_to_path("/user/hand/left/input/aim/pose") xr::Binding::new(
.unwrap(), &hands[1].action_pose,
), instance.string_to_path("/user/hand/right/input/aim/pose")?,
xr::Binding::new( ),
&hands[1].action_pose, xr::Binding::new(
instance &hands[0].action_click,
.string_to_path("/user/hand/right/input/aim/pose") instance.string_to_path("/user/hand/left/input/select/click")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_click,
&hands[0].action_click, instance.string_to_path("/user/hand/right/input/select/click")?,
instance ),
.string_to_path("/user/hand/left/input/select/click") xr::Binding::new(
.unwrap(), &hands[0].action_show_hide,
), instance.string_to_path("/user/hand/left/input/menu/click")?,
xr::Binding::new( ),
&hands[1].action_click, xr::Binding::new(
instance &hands[0].action_haptics,
.string_to_path("/user/hand/right/input/select/click") instance.string_to_path("/user/hand/left/output/haptic")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_haptics,
&hands[0].action_show_hide, instance.string_to_path("/user/hand/right/output/haptic")?,
instance ),
.string_to_path("/user/hand/left/input/menu/click") ],
.unwrap(), )?;
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance let path = instance.string_to_path("/interaction_profiles/oculus/touch_controller")?;
.string_to_path("/interaction_profiles/oculus/touch_controller") instance.suggest_interaction_profile_bindings(
.unwrap(); path,
instance &[
.suggest_interaction_profile_bindings( xr::Binding::new(
path, &hands[0].action_pose,
&[ instance.string_to_path("/user/hand/left/input/aim/pose")?,
xr::Binding::new( ),
&hands[0].action_pose, xr::Binding::new(
instance &hands[1].action_pose,
.string_to_path("/user/hand/left/input/aim/pose") instance.string_to_path("/user/hand/right/input/aim/pose")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_click,
&hands[1].action_pose, instance.string_to_path("/user/hand/left/input/trigger/value")?,
instance ),
.string_to_path("/user/hand/right/input/aim/pose") xr::Binding::new(
.unwrap(), &hands[1].action_click,
), instance.string_to_path("/user/hand/right/input/trigger/value")?,
xr::Binding::new( ),
&hands[0].action_click, xr::Binding::new(
instance &hands[0].action_grab,
.string_to_path("/user/hand/left/input/trigger/value") instance.string_to_path("/user/hand/left/input/squeeze/value")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_grab,
&hands[1].action_click, instance.string_to_path("/user/hand/right/input/squeeze/value")?,
instance ),
.string_to_path("/user/hand/right/input/trigger/value") xr::Binding::new(
.unwrap(), &hands[0].action_scroll,
), instance.string_to_path("/user/hand/left/input/thumbstick/y")?,
xr::Binding::new( ),
&hands[0].action_grab, xr::Binding::new(
instance &hands[1].action_scroll,
.string_to_path("/user/hand/left/input/squeeze/value") instance.string_to_path("/user/hand/right/input/thumbstick/y")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_show_hide,
&hands[1].action_grab, instance.string_to_path("/user/hand/left/input/y/click")?,
instance ),
.string_to_path("/user/hand/right/input/squeeze/value") xr::Binding::new(
.unwrap(), &hands[0].action_click_modifier_right,
), instance.string_to_path("/user/hand/left/input/y/touch")?,
xr::Binding::new( ),
&hands[0].action_scroll, xr::Binding::new(
instance &hands[1].action_click_modifier_right,
.string_to_path("/user/hand/left/input/thumbstick/y") instance.string_to_path("/user/hand/right/input/b/touch")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_click_modifier_middle,
&hands[1].action_scroll, instance.string_to_path("/user/hand/left/input/x/touch")?,
instance ),
.string_to_path("/user/hand/right/input/thumbstick/y") xr::Binding::new(
.unwrap(), &hands[1].action_click_modifier_middle,
), instance.string_to_path("/user/hand/right/input/a/touch")?,
xr::Binding::new( ),
&hands[0].action_show_hide, xr::Binding::new(
instance &hands[0].action_haptics,
.string_to_path("/user/hand/left/input/y/click") instance.string_to_path("/user/hand/left/output/haptic")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_haptics,
&hands[0].action_click_modifier_right, instance.string_to_path("/user/hand/right/output/haptic")?,
instance ),
.string_to_path("/user/hand/left/input/y/touch") ],
.unwrap(), )?;
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance
.string_to_path("/user/hand/right/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance
.string_to_path("/user/hand/left/input/x/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance
.string_to_path("/user/hand/right/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance let path = instance.string_to_path("/interaction_profiles/valve/index_controller")?;
.string_to_path("/interaction_profiles/valve/index_controller") instance.suggest_interaction_profile_bindings(
.unwrap(); path,
instance &[
.suggest_interaction_profile_bindings( xr::Binding::new(
path, &hands[0].action_pose,
&[ instance.string_to_path("/user/hand/left/input/aim/pose")?,
xr::Binding::new( ),
&hands[0].action_pose, xr::Binding::new(
instance &hands[1].action_pose,
.string_to_path("/user/hand/left/input/aim/pose") instance.string_to_path("/user/hand/right/input/aim/pose")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_click,
&hands[1].action_pose, instance.string_to_path("/user/hand/left/input/trigger/value")?,
instance ),
.string_to_path("/user/hand/right/input/aim/pose") xr::Binding::new(
.unwrap(), &hands[1].action_click,
), instance.string_to_path("/user/hand/right/input/trigger/value")?,
xr::Binding::new( ),
&hands[0].action_click, xr::Binding::new(
instance &hands[0].action_grab,
.string_to_path("/user/hand/left/input/trigger/value") instance.string_to_path("/user/hand/left/input/squeeze/value")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_grab,
&hands[1].action_click, instance.string_to_path("/user/hand/right/input/squeeze/value")?,
instance ),
.string_to_path("/user/hand/right/input/trigger/value") xr::Binding::new(
.unwrap(), &hands[0].action_scroll,
), instance.string_to_path("/user/hand/left/input/thumbstick/y")?,
xr::Binding::new( ),
&hands[0].action_grab, xr::Binding::new(
instance &hands[1].action_scroll,
.string_to_path("/user/hand/left/input/squeeze/value") instance.string_to_path("/user/hand/right/input/thumbstick/y")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_alt_click,
&hands[1].action_grab, instance.string_to_path("/user/hand/left/input/trackpad/force")?,
instance ),
.string_to_path("/user/hand/right/input/squeeze/value") xr::Binding::new(
.unwrap(), &hands[1].action_alt_click,
), instance.string_to_path("/user/hand/right/input/trackpad/force")?,
xr::Binding::new( ),
&hands[0].action_scroll, xr::Binding::new(
instance &hands[0].action_show_hide,
.string_to_path("/user/hand/left/input/thumbstick/y") instance.string_to_path("/user/hand/left/input/b/click")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_click_modifier_right,
&hands[1].action_scroll, instance.string_to_path("/user/hand/left/input/b/touch")?,
instance ),
.string_to_path("/user/hand/right/input/thumbstick/y") xr::Binding::new(
.unwrap(), &hands[1].action_click_modifier_right,
), instance.string_to_path("/user/hand/right/input/b/touch")?,
xr::Binding::new( ),
&hands[0].action_alt_click, xr::Binding::new(
instance &hands[0].action_click_modifier_middle,
.string_to_path("/user/hand/left/input/trackpad/force") instance.string_to_path("/user/hand/left/input/a/touch")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_click_modifier_middle,
&hands[1].action_alt_click, instance.string_to_path("/user/hand/right/input/a/touch")?,
instance ),
.string_to_path("/user/hand/right/input/trackpad/force") xr::Binding::new(
.unwrap(), &hands[0].action_haptics,
), instance.string_to_path("/user/hand/left/output/haptic")?,
xr::Binding::new( ),
&hands[0].action_show_hide, xr::Binding::new(
instance &hands[1].action_haptics,
.string_to_path("/user/hand/left/input/b/click") instance.string_to_path("/user/hand/right/output/haptic")?,
.unwrap(), ),
), ],
xr::Binding::new( )?;
&hands[0].action_click_modifier_right,
instance
.string_to_path("/user/hand/left/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_right,
instance
.string_to_path("/user/hand/right/input/b/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_click_modifier_middle,
instance
.string_to_path("/user/hand/left/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_click_modifier_middle,
instance
.string_to_path("/user/hand/right/input/a/touch")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
let path = instance let path = instance.string_to_path("/interaction_profiles/htc/vive_controller")?;
.string_to_path("/interaction_profiles/htc/vive_controller") instance.suggest_interaction_profile_bindings(
.unwrap(); path,
instance &[
.suggest_interaction_profile_bindings( xr::Binding::new(
path, &hands[0].action_pose,
&[ instance.string_to_path("/user/hand/left/input/aim/pose")?,
xr::Binding::new( ),
&hands[0].action_pose, xr::Binding::new(
instance &hands[1].action_pose,
.string_to_path("/user/hand/left/input/aim/pose") instance.string_to_path("/user/hand/right/input/aim/pose")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[1].action_click,
&hands[1].action_pose, instance.string_to_path("/user/hand/right/input/trigger/value")?,
instance ),
.string_to_path("/user/hand/right/input/aim/pose") xr::Binding::new(
.unwrap(), &hands[0].action_grab,
), instance.string_to_path("/user/hand/left/input/squeeze/click")?,
xr::Binding::new( ),
&hands[0].action_click, xr::Binding::new(
instance &hands[1].action_grab,
.string_to_path("/user/hand/left/input/trigger/value") instance.string_to_path("/user/hand/right/input/squeeze/click")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_scroll,
&hands[1].action_click, instance.string_to_path("/user/hand/left/input/trackpad/y")?,
instance ),
.string_to_path("/user/hand/right/input/trigger/value") xr::Binding::new(
.unwrap(), &hands[1].action_scroll,
), instance.string_to_path("/user/hand/right/input/trackpad/y")?,
xr::Binding::new( ),
&hands[0].action_grab, xr::Binding::new(
instance &hands[0].action_show_hide,
.string_to_path("/user/hand/left/input/squeeze/click") instance.string_to_path("/user/hand/left/input/menu/click")?,
.unwrap(), ),
), xr::Binding::new(
xr::Binding::new( &hands[0].action_haptics,
&hands[1].action_grab, instance.string_to_path("/user/hand/left/output/haptic")?,
instance ),
.string_to_path("/user/hand/right/input/squeeze/click") xr::Binding::new(
.unwrap(), &hands[1].action_haptics,
), instance.string_to_path("/user/hand/right/output/haptic")?,
xr::Binding::new( ),
&hands[0].action_scroll, ],
instance )?;
.string_to_path("/user/hand/left/input/trackpad/y")
.unwrap(), Ok(())
),
xr::Binding::new(
&hands[1].action_scroll,
instance
.string_to_path("/user/hand/right/input/trackpad/y")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_show_hide,
instance
.string_to_path("/user/hand/left/input/menu/click")
.unwrap(),
),
xr::Binding::new(
&hands[0].action_haptics,
instance
.string_to_path("/user/hand/left/output/haptic")
.unwrap(),
),
xr::Binding::new(
&hands[1].action_haptics,
instance
.string_to_path("/user/hand/right/output/haptic")
.unwrap(),
),
],
)
.unwrap();
} }

View File

@@ -57,7 +57,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let mut app_state = { let mut app_state = {
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system); let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system);
AppState::from_graphics(graphics) AppState::from_graphics(graphics)?
}; };
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state); let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state);
@@ -109,7 +109,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id; let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id;
let input_source = input::OpenXrInputSource::new(&xr_state); let input_source = input::OpenXrInputSource::new(&xr_state)?;
let mut session_running = false; let mut session_running = false;
let mut event_storage = xr::EventDataBuffer::new(); let mut event_storage = xr::EventDataBuffer::new();
@@ -136,7 +136,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
SessionStateChanged(e) => { SessionStateChanged(e) => {
// Session state change is where we can begin and end sessions, as well as // Session state change is where we can begin and end sessions, as well as
// find quit messages! // find quit messages!
println!("entered state {:?}", e.state()); log::info!("entered state {:?}", e.state());
match e.state() { match e.state() {
xr::SessionState::READY => { xr::SessionState::READY => {
xr_state.session.begin(VIEW_TYPE).unwrap(); xr_state.session.begin(VIEW_TYPE).unwrap();
@@ -156,7 +156,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
break 'main_loop; break 'main_loop;
} }
EventsLost(e) => { EventsLost(e) => {
println!("lost {} events", e.lost_event_count()); log::warn!("lost {} events", e.lost_event_count());
} }
_ => {} _ => {}
} }
@@ -200,7 +200,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
} }
app_state.input_state.pre_update(); app_state.input_state.pre_update();
input_source.update(&xr_state, &mut app_state); input_source.update(&xr_state, &mut app_state)?;
app_state.input_state.post_update(); app_state.input_state.post_update();
if app_state if app_state

View File

@@ -135,7 +135,7 @@ pub fn load_general() -> GeneralConfig {
continue; continue;
} }
println!("Loading config file {}", path.path().to_string_lossy()); log::info!("Loading config file {}", path.path().to_string_lossy());
if let Ok(data) = std::fs::read_to_string(path.path()) { if let Ok(data) = std::fs::read_to_string(path.path()) {
yaml_data.push('\n'); // Just in case, if end of the config file was not newline yaml_data.push('\n'); // Just in case, if end of the config file was not newline

View File

@@ -45,7 +45,7 @@ fn get_config_file_path(filename: &str) -> PathBuf {
pub fn load(filename: &str) -> Option<String> { pub fn load(filename: &str) -> Option<String> {
let path = get_config_file_path(filename); let path = get_config_file_path(filename);
println!("Loading config {}", path.to_string_lossy()); log::info!("Loading config {}", path.to_string_lossy());
if let Ok(data) = fs::read_to_string(path) { if let Ok(data) = fs::read_to_string(path) {
Some(data) Some(data)
@@ -60,7 +60,7 @@ macro_rules! load_with_fallback {
if let Some(data) = config_io::load($filename) { if let Some(data) = config_io::load($filename) {
data data
} else { } else {
println!( log::info!(
"Config {}/{} does not exist, using internal fallback", "Config {}/{} does not exist, using internal fallback",
config_io::CONFIG_ROOT_PATH.to_string_lossy(), config_io::CONFIG_ROOT_PATH.to_string_lossy(),
$filename $filename

View File

@@ -184,8 +184,9 @@ impl HidProvider for UInputProvider {
for i in 0..7 { for i in 0..7 {
let m = 1 << i; let m = 1 << i;
if changed & m != 0 { if changed & m != 0 {
let vk = MODS_TO_KEYS.get(m).unwrap()[0] as u16; if let Some(vk) = MODS_TO_KEYS.get(m).into_iter().flatten().next() {
self.send_key(vk, modifiers & m != 0); self.send_key(*vk as u16, modifiers & m != 0);
}
} }
} }
self.cur_modifiers = modifiers; self.cur_modifiers = modifiers;

View File

@@ -9,15 +9,25 @@ mod overlays;
mod shaders; mod shaders;
mod state; mod state;
use std::sync::{ use std::{
atomic::{AtomicBool, Ordering}, io::{stdout, IsTerminal},
Arc, sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
}; };
use env_logger::Env; use flexi_logger::FileSpec;
fn main() -> Result<(), Box<dyn std::error::Error>> {
if stdout().is_terminal() {
flexi_logger::Logger::try_with_env_or_str("info")?.start()?;
} else {
flexi_logger::Logger::try_with_env_or_str("info")?
.log_to_file(FileSpec::default().directory("/tmp"))
.start()?;
}
fn main() {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
log::info!( log::info!(
"Welcome to {} version {}!", "Welcome to {} version {}!",
env!("CARGO_PKG_NAME"), env!("CARGO_PKG_NAME"),
@@ -27,7 +37,7 @@ fn main() {
#[cfg(feature = "openvr")] #[cfg(feature = "openvr")]
if std::env::args().any(|arg| arg == "--uninstall") { if std::env::args().any(|arg| arg == "--uninstall") {
crate::backend::openvr::openvr_uninstall(); crate::backend::openvr::openvr_uninstall();
return; return Ok(());
} }
let running = Arc::new(AtomicBool::new(true)); let running = Arc::new(AtomicBool::new(true));
@@ -38,33 +48,30 @@ fn main() {
} }
}); });
#[cfg(all(feature = "openxr", feature = "openvr"))]
auto_run(running); auto_run(running);
// TODO: Handle error messages if using cherry-picked features Ok(())
#[cfg(all(feature = "openvr", not(feature = "openxr")))]
let _ = crate::backend::openvr::openvr_run(running);
#[cfg(all(feature = "openxr", not(feature = "openvr")))]
let _ = crate::backend::openxr::openxr_run(running);
#[cfg(not(any(feature = "openxr", feature = "openvr")))]
compile_error!("You must enable at least one backend feature (openxr or openvr)");
} }
#[cfg(all(feature = "openxr", feature = "openvr"))] #[cfg(all(feature = "openxr", feature = "openvr"))]
fn auto_run(running: Arc<AtomicBool>) { fn auto_run(running: Arc<AtomicBool>) {
use crate::backend::openvr::openvr_run;
use crate::backend::openxr::openxr_run;
use backend::common::BackendError; use backend::common::BackendError;
let Err(BackendError::NotSupported) = openxr_run(running.clone()) else { #[cfg(feature = "openxr")]
return; {
}; use crate::backend::openxr::openxr_run;
let Err(BackendError::NotSupported) = openxr_run(running.clone()) else {
return;
};
}
let Err(BackendError::NotSupported) = openvr_run(running) else { #[cfg(feature = "openxr")]
return; {
}; use crate::backend::openvr::openvr_run;
let Err(BackendError::NotSupported) = openvr_run(running) else {
return;
};
}
log::error!("No supported backends found"); log::error!("No supported backends found");
} }

View File

@@ -87,7 +87,10 @@ where
}); });
} else if let Some(exec_args) = LAYOUT.exec_commands.get(key) { } else if let Some(exec_args) = LAYOUT.exec_commands.get(key) {
maybe_state = Some(KeyButtonData::Exec { maybe_state = Some(KeyButtonData::Exec {
program: exec_args.first().unwrap().clone(), program: exec_args
.first()
.expect("Keyboard: Invalid EXEC args")
.clone(),
args: exec_args.iter().skip(1).cloned().collect(), args: exec_args.iter().skip(1).cloned().collect(),
}); });
} else { } else {

View File

@@ -481,9 +481,10 @@ where
let token = pw_token_store.get(display_name).map(|s| s.as_str()); let token = pw_token_store.get(display_name).map(|s| s.as_str());
if let Some(t) = token { if let Some(t) = token {
println!( log::info!(
"Found existing Pipewire token for display {}: {}", "Found existing Pipewire token for display {}: {}",
display_name, t display_name,
t
); );
} }
@@ -495,7 +496,7 @@ where
.insert(String::from(display_name), token.clone()) .insert(String::from(display_name), token.clone())
.is_none() .is_none()
{ {
println!("Adding Pipewire token {}", token); log::info!("Adding Pipewire token {}", token);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
use anyhow::bail;
use glam::{Quat, Vec3}; use glam::{Quat, Vec3};
use vulkano::format::Format; use vulkano::format::Format;
@@ -27,30 +28,30 @@ pub struct AppState {
} }
impl AppState { impl AppState {
pub fn from_graphics(graphics: Arc<WlxGraphics>) -> Self { pub fn from_graphics(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
// insert shared resources // insert shared resources
{ {
let Ok(mut shaders) = graphics.shared_shaders.write() else { let Ok(mut shaders) = graphics.shared_shaders.write() else {
panic!("Shared Shaders RwLock poisoned"); bail!("Failed to lock shared shaders");
}; };
let shader = vert_common::load(graphics.device.clone()).unwrap(); let shader = vert_common::load(graphics.device.clone())?;
shaders.insert("vert_common", shader); shaders.insert("vert_common", shader);
let shader = frag_color::load(graphics.device.clone()).unwrap(); let shader = frag_color::load(graphics.device.clone())?;
shaders.insert("frag_color", shader); shaders.insert("frag_color", shader);
let shader = frag_glyph::load(graphics.device.clone()).unwrap(); let shader = frag_glyph::load(graphics.device.clone())?;
shaders.insert("frag_glyph", shader); shaders.insert("frag_glyph", shader);
let shader = frag_sprite::load(graphics.device.clone()).unwrap(); let shader = frag_sprite::load(graphics.device.clone())?;
shaders.insert("frag_sprite", shader); shaders.insert("frag_sprite", shader);
let shader = frag_srgb::load(graphics.device.clone()).unwrap(); let shader = frag_srgb::load(graphics.device.clone())?;
shaders.insert("frag_srgb", shader); shaders.insert("frag_srgb", shader);
} }
AppState { Ok(AppState {
fc: FontCache::new(), fc: FontCache::new(),
session: AppSession::load(), session: AppSession::load(),
tasks: TaskContainer::new(), tasks: TaskContainer::new(),
@@ -58,7 +59,7 @@ impl AppState {
format: Format::R8G8B8A8_UNORM, format: Format::R8G8B8A8_UNORM,
input_state: InputState::new(), input_state: InputState::new(),
hid_provider: crate::hid::initialize(), hid_provider: crate::hid::initialize(),
} })
} }
} }
@@ -81,7 +82,7 @@ pub struct AppSession {
impl AppSession { impl AppSession {
pub fn load() -> Self { pub fn load() -> Self {
let config_root_path = config_io::ensure_config_root(); let config_root_path = config_io::ensure_config_root();
println!("Config root path: {}", config_root_path.to_string_lossy()); log::info!("Config root path: {}", config_root_path.to_string_lossy());
let config = GeneralConfig::load_from_disk(); let config = GeneralConfig::load_from_disk();
AppSession { AppSession {