diff --git a/Cargo.lock b/Cargo.lock index 3c9a992..9227eda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -542,16 +542,16 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.2" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c69fae65a523209d34240b60abe0c42d33d1045d445c0839d8a4894a736e2d" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ "bitflags 2.4.2", "cexpr", "clang-sys", + "itertools 0.12.1", "lazy_static", "lazycell", - "peeking_take_while", "proc-macro2", "quote", "regex", @@ -924,7 +924,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" dependencies = [ - "bindgen 0.69.2", + "bindgen 0.69.4", ] [[package]] @@ -1648,9 +1648,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1812,6 +1812,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -1886,6 +1895,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + [[package]] name = "lazy_static" version = "1.4.0" @@ -2109,9 +2124,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -2412,7 +2427,7 @@ dependencies = [ [[package]] name = "ovr_overlay" version = "0.0.0" -source = "git+https://github.com/galister/ovr_overlay_oyasumi#0bcb9a8ea71701aada232e30c88cf3a52328e8e0" +source = "git+https://github.com/galister/ovr_overlay_oyasumi#df243248c4eb021ae43fbb96e3fe1c5b9fe48be5" dependencies = [ "byteorder", "derive_more", @@ -2427,7 +2442,7 @@ dependencies = [ [[package]] name = "ovr_overlay_sys" version = "0.0.0" -source = "git+https://github.com/galister/ovr_overlay_oyasumi#0bcb9a8ea71701aada232e30c88cf3a52328e8e0" +source = "git+https://github.com/galister/ovr_overlay_oyasumi#df243248c4eb021ae43fbb96e3fe1c5b9fe48be5" dependencies = [ "autocxx", "autocxx-build", @@ -3269,9 +3284,9 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", "arrayvec", @@ -3283,9 +3298,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ "arrayref", "bytemuck", @@ -4150,9 +4165,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.36" +version = "0.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818ce546a11a9986bc24f93d0cdf38a8a1a400f1473ea8c82e59f6e0ffab9249" +checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" dependencies = [ "memchr", ] @@ -4195,6 +4210,7 @@ dependencies = [ "idmap", "idmap-derive", "input-linux", + "json", "libc", "log", "once_cell", @@ -4273,11 +4289,11 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "xdg-home" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ - "nix 0.26.4", + "libc", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 681dd12..d594b38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ glam = { version = "0.24.1", features = ["approx"] } idmap = "0.2.21" idmap-derive = "0.1.2" input-linux = "0.6.0" +json = { version = "0.12.4", optional = true } libc = "0.2.147" log = "0.4.20" once_cell = "1.18.0" @@ -45,7 +46,7 @@ wlx-capture = { git = "https://github.com/galister/wlx-capture" } xdg = "2.5.2" [features] -openvr = ["dep:ovr_overlay"] +openvr = ["dep:ovr_overlay", "dep:json"] openxr = ["dep:openxr"] default = ["openvr", "openxr"] diff --git a/src/backend/openvr/manifest.rs b/src/backend/openvr/manifest.rs new file mode 100644 index 0000000..08d99e4 --- /dev/null +++ b/src/backend/openvr/manifest.rs @@ -0,0 +1,72 @@ +use std::{fs::File, io::Read}; + +use json::{array, object}; +use ovr_overlay::applications::ApplicationsManager; + +use crate::config_io::CONFIG_ROOT_PATH; + +const APP_KEY: &str = "galister.wlxoverlay-s"; + +pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) { + let executable_pathbuf = std::env::current_exe().unwrap(); + let executable_path = executable_pathbuf.to_str().unwrap(); + let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest"); + + if let Ok(true) = app_mgr.is_application_installed(APP_KEY) { + if let Ok(mut file) = File::open(&manifest_path) { + let mut buf = String::new(); + if let Ok(_) = file.read_to_string(&mut buf) { + let manifest: json::JsonValue = json::parse(&buf).unwrap(); + if manifest["applications"][0]["binary_path_linux"] == executable_path { + log::info!("Manifest already up to date"); + return; + } + } + } + } + + let manifest = object! { + source: "builtin", + applications: array![ + object! { + app_key: APP_KEY, + launch_type: "binary", + binary_path_linux: executable_path, + is_dashboard_overlay: true, + strings: object!{ + "en_us": object!{ + name: "WlxOverlay-S", + description: "A lightweight Wayland desktop overlay for OpenVR/OpenXR", + }, + }, + }, + ], + }; + + let Ok(mut file) = File::create(&manifest_path) else { + log::error!("Failed to create manifest file at {:?}", manifest_path); + return; + }; + + let Ok(()) = manifest.write(&mut file) else { + log::error!("Failed to write manifest file at {:?}", manifest_path); + return; + }; + + let Ok(()) = app_mgr.add_application_manifest(&manifest_path, false) else { + log::error!("Failed to add manifest to OpenVR"); + return; + }; +} + +pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) { + let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest"); + + if let Ok(true) = app_mgr.is_application_installed(APP_KEY) { + let Ok(()) = app_mgr.remove_application_manifest(&manifest_path) else { + log::error!("Failed to remove manifest from OpenVR"); + return; + }; + log::info!("Uninstalled manifest"); + } +} diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 301060e..4436eba 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -20,22 +20,34 @@ use vulkano::{ use crate::{ backend::{ input::interact, - openvr::{input::OpenVrInputSource, lines::LinePool}, + openvr::{input::OpenVrInputSource, lines::LinePool, manifest::install_manifest}, }, graphics::WlxGraphics, state::AppState, }; -use self::{input::action_manifest_path, overlay::OpenVrOverlayData}; +use self::{input::action_manifest_path, manifest::uninstall_manifest, overlay::OpenVrOverlayData}; use super::common::{BackendError, OverlayContainer, TaskType}; pub mod helpers; pub mod input; pub mod lines; +pub mod manifest; pub mod overlay; pub mod playspace; +pub fn openvr_uninstall() { + let app_type = EVRApplicationType::VRApplication_Overlay; + let Ok(context) = ovr_overlay::Context::init(app_type) else { + log::error!("Uninstall failed: could not reach OpenVR"); + return; + }; + + let mut app_mgr = context.applications_mngr(); + uninstall_manifest(&mut app_mgr); +} + pub fn openvr_run(running: Arc) -> Result<(), BackendError> { let app_type = EVRApplicationType::VRApplication_Overlay; let Ok(context) = ovr_overlay::Context::init(app_type) else { @@ -47,6 +59,7 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { let mut overlay_mngr = context.overlay_mngr(); //let mut settings_mngr = context.settings_mngr(); + let mut app_mgr = context.applications_mngr(); let mut input_mngr = context.input_mngr(); let mut system_mngr = context.system_mngr(); let mut chaperone_mgr = context.chaperone_setup_mngr(); @@ -69,6 +82,8 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { AppState::from_graphics(graphics) }; + install_manifest(&mut app_mgr); + let mut overlays = OverlayContainer::::new(&mut state); let mut space_mover = playspace::PlayspaceMover::new(); @@ -210,7 +225,7 @@ pub fn openvr_run(running: Arc) -> Result<(), BackendError> { let mut seconds_since_vsync = 0f32; std::thread::sleep(Duration::from_secs_f32( if system_mngr.get_time_since_last_vsync(&mut seconds_since_vsync, &mut 0u64) { - frame_time - (seconds_since_vsync % frame_time) + (frame_time - seconds_since_vsync).max(0.0) } else { frame_time }, diff --git a/src/main.rs b/src/main.rs index 4845a1f..92b86cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,12 @@ fn main() { env!("CARGO_PKG_VERSION") ); + #[cfg(feature = "openvr")] + if std::env::args().any(|arg| arg == "--uninstall") { + crate::backend::openvr::openvr_uninstall(); + return; + } + let running = Arc::new(AtomicBool::new(true)); let _ = ctrlc::set_handler({ let running = running.clone();