From 1ac253ecbfd605439b0117608014daad98fc393a Mon Sep 17 00:00:00 2001 From: Etch9 Date: Tue, 25 Feb 2025 18:02:34 +0000 Subject: [PATCH 01/33] fix: libnotify headers path in wivrn depcheck --- src/depcheck/wivrn_deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/depcheck/wivrn_deps.rs b/src/depcheck/wivrn_deps.rs index fc704d9..acf9a35 100644 --- a/src/depcheck/wivrn_deps.rs +++ b/src/depcheck/wivrn_deps.rs @@ -253,7 +253,7 @@ fn wivrn_deps() -> Vec { Dependency { name: "libnotify-dev".into(), dep_type: DepType::Include, - filename: "openssl/ssl3.h".into(), + filename: "libnotify/notify.h".into(), packages: HashMap::from([ (LinuxDistro::Arch, "libnotify".into()), (LinuxDistro::Alpine, "libnotify-dev".into()), From e117986715e1e9ef955009ad7f03ec110aa14940 Mon Sep 17 00:00:00 2001 From: Bones Date: Sun, 2 Mar 2025 13:51:58 -0500 Subject: [PATCH 02/33] chore: update version to 3.0.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- data/org.gabmus.envision.metainfo.xml.in.in | 8 ++++++++ meson.build | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 312a7aa..bc56ea6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,7 +563,7 @@ dependencies = [ [[package]] name = "envision" -version = "3.0.0" +version = "3.0.1" dependencies = [ "anyhow", "ash", diff --git a/Cargo.toml b/Cargo.toml index f41c7f6..575b302 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "envision" -version = "3.0.0" +version = "3.0.1" edition = "2021" authors = [ "Gabriele Musco ", diff --git a/data/org.gabmus.envision.metainfo.xml.in.in b/data/org.gabmus.envision.metainfo.xml.in.in index cbe2b3a..8925605 100644 --- a/data/org.gabmus.envision.metainfo.xml.in.in +++ b/data/org.gabmus.envision.metainfo.xml.in.in @@ -30,6 +30,14 @@ @REPO_URL@/issues + + +

Fixes

+
    +
  • libnotify headers path in wivrn depcheck
  • +
+
+

Breaking changes

diff --git a/meson.build b/meson.build index 8a4176b..7e406b2 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'envision', 'rust', - version: '3.0.0', # version number row + version: '3.0.1', # version number row meson_version: '>= 0.59', license: 'AGPL-3.0-or-later', ) From db45103d1bc23d56692571d652f56f8866dc956d Mon Sep 17 00:00:00 2001 From: hypevhs Date: Thu, 13 Mar 2025 11:30:35 -0500 Subject: [PATCH 03/33] fix(monado dependencies): use wayland-protocols-devel on Fedora --- src/depcheck/monado_deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index 93055d3..8c555fc 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -37,7 +37,7 @@ fn monado_deps() -> Vec { packages: HashMap::from([ (LinuxDistro::Arch, "wayland-protocols".into()), (LinuxDistro::Debian, "wayland-protocols".into()), - (LinuxDistro::Fedora, "wayland-protocols".into()), + (LinuxDistro::Fedora, "wayland-protocols-devel".into()), (LinuxDistro::Gentoo, "dev-libs/wayland-protocols".into()), (LinuxDistro::Suse, "wayland-protocols-devel".into()), ]), From f38199601ed7d88fbc3ce74c2403960e1f71ee76 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sun, 6 Apr 2025 12:33:26 +0200 Subject: [PATCH 04/33] feat: remove monado vulkan layers check for nvidia fixes #208 --- dist/arch/PKGBUILD | 1 - src/ui/about_dialog.rs | 6 ------ src/ui/app.rs | 1 - src/ui/main_view.rs | 33 --------------------------------- src/vulkaninfo.rs | 41 +++++++++-------------------------------- 5 files changed, 9 insertions(+), 73 deletions(-) diff --git a/dist/arch/PKGBUILD b/dist/arch/PKGBUILD index 3ff8a64..ee1a4b2 100644 --- a/dist/arch/PKGBUILD +++ b/dist/arch/PKGBUILD @@ -33,7 +33,6 @@ makedepends=( ) optdepends=( 'libudev0-shim: steamvr_lh lighthouse driver support' - 'monado-vulkan-layers-git: Vulkan layers for NVIDIA users' ) provides=(envision) conflicts=(envision) diff --git a/src/ui/about_dialog.rs b/src/ui/about_dialog.rs index 8f4235e..795d546 100644 --- a/src/ui/about_dialog.rs +++ b/src/ui/about_dialog.rs @@ -81,12 +81,6 @@ pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo .map(|i| i.gpu_names.join(", ")) .unwrap_or(UNKNOWN.into()) ), - format!( - "Monado Vulkan Layers: {}", - vkinfo - .map(|i| i.has_monado_vulkan_layers.to_string()) - .unwrap_or(UNKNOWN.into()) - ), format!("Detected XR Devices: {}", { let devs = PhysicalXRDevice::from_usb(); if devs.is_empty() { diff --git a/src/ui/app.rs b/src/ui/app.rs index 98510a3..5df4dba 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -998,7 +998,6 @@ impl AsyncComponent for App { config: config.clone(), selected_profile: selected_profile.clone(), root_win: root.clone().into(), - vkinfo: vkinfo.clone(), }) .forward(sender.input_sender(), |message| match message { MainViewOutMsg::DoStartStopXRService => Msg::DoStartStopXRService, diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index c81a5a9..ce5f7a6 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -25,7 +25,6 @@ use crate::{ file_utils::{get_writer, mount_has_nosuid}, steamvr_utils::chaperone_info_exists, }, - vulkaninfo::VulkanInfo, wivrn_dbus, xr_devices::XRDevice, }; @@ -75,8 +74,6 @@ pub struct MainView { #[tracker::do_not_track] profile_export_action: gtk::gio::SimpleAction, xrservice_ready: bool, - #[tracker::do_not_track] - vkinfo: Option, wivrn_pairing_mode: bool, wivrn_pin: Option, wivrn_supports_pairing: bool, @@ -126,7 +123,6 @@ pub struct MainViewInit { pub config: Config, pub selected_profile: Profile, pub root_win: gtk::Window, - pub vkinfo: Option, } impl MainView { @@ -461,34 +457,6 @@ impl AsyncComponent for MainView { set_wrap_mode: gtk::pango::WrapMode::Word, } }, - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_hexpand: true, - set_vexpand: false, - set_spacing: 12, - add_css_class: "card", - add_css_class: "padded", - set_visible: model - .vkinfo - .as_ref() - .is_some_and( - |i| i.has_nvidia_gpu && !i.has_monado_vulkan_layers - ), - warning_heading(), - gtk::Label { - set_label: concat!( - "An Nvidia GPU has been detected, but it ", - "seems you don't have the Monado Vulkan Layers ", - "installed on your system.\n\nInstall the ", - "Monado Vulkan Layers or your XR session will ", - "crash." - ), - add_css_class: "warning", - set_xalign: 0.0, - set_wrap: true, - set_wrap_mode: gtk::pango::WrapMode::Word, - } - }, gtk::Box { set_orientation: gtk::Orientation::Vertical, set_hexpand: true, @@ -1103,7 +1071,6 @@ impl AsyncComponent for MainView { xrservice_ready: false, profile_delete_action, profile_export_action, - vkinfo: init.vkinfo, wivrn_pairing_mode: false, wivrn_supports_pairing: false, wivrn_pin: None, diff --git a/src/vulkaninfo.rs b/src/vulkaninfo.rs index a8f8110..6d76a92 100644 --- a/src/vulkaninfo.rs +++ b/src/vulkaninfo.rs @@ -5,12 +5,10 @@ use ash::{ #[derive(Debug, Clone)] pub struct VulkanInfo { - pub has_nvidia_gpu: bool, - pub has_monado_vulkan_layers: bool, pub gpu_names: Vec, } -const NVIDIA_VENDOR_ID: u32 = 0x10de; +// const NVIDIA_VENDOR_ID: u32 = 0x10de; impl VulkanInfo { /// # Safety @@ -25,40 +23,19 @@ impl VulkanInfo { None, ) }?; - let mut has_nvidia_gpu = false; - let mut has_monado_vulkan_layers = false; let gpu_names = unsafe { instance.enumerate_physical_devices() }? .into_iter() .filter_map(|d| { - let props = unsafe { instance.get_physical_device_properties(d) }; - if props.vendor_id == NVIDIA_VENDOR_ID { - has_nvidia_gpu = true; - } - if !has_monado_vulkan_layers { - has_monado_vulkan_layers = - unsafe { instance.enumerate_device_layer_properties(d) } - .ok() - .map(|layerprops| { - layerprops.iter().any(|lp| { - lp.layer_name_as_c_str().is_ok_and(|name| { - name.to_string_lossy() - == "VK_LAYER_MND_enable_timeline_semaphore" - }) - }) - }) - == Some(true); - } - props - .device_name_as_c_str() - .ok() - .map(|cs| cs.to_string_lossy().to_string()) + Some( + unsafe { instance.get_physical_device_properties(d) } + .device_name_as_c_str() + .ok()? + .to_string_lossy() + .to_string(), + ) }) .collect(); unsafe { instance.destroy_instance(None) }; - Ok(Self { - gpu_names, - has_nvidia_gpu, - has_monado_vulkan_layers, - }) + Ok(Self { gpu_names }) } } From 2fc33b10b0050f3b836b234bd5674f7192c215d6 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sun, 6 Apr 2025 12:58:54 +0200 Subject: [PATCH 05/33] feat: add support for vapor openvr compatibility module --- src/builders/build_vapor.rs | 85 +++++++++++++++++++++++++++++++++++++ src/builders/mod.rs | 1 + src/profile.rs | 12 ++++-- src/ui/app.rs | 6 ++- 4 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 src/builders/build_vapor.rs diff --git a/src/builders/build_vapor.rs b/src/builders/build_vapor.rs new file mode 100644 index 0000000..10206fe --- /dev/null +++ b/src/builders/build_vapor.rs @@ -0,0 +1,85 @@ +use crate::{ + build_tools::{cmake::Cmake, git::Git}, + profile::Profile, + termcolor::TermColor, + ui::job_worker::job::{FuncWorkerData, FuncWorkerOut, WorkerJob}, + util::file_utils::{copy_file, rm_rf}, +}; +use std::{ + collections::{HashMap, VecDeque}, + fs::create_dir_all, + path::Path, +}; + +pub fn get_build_vapor_jobs(profile: &Profile, clean_build: bool) -> VecDeque { + let mut jobs = VecDeque::::new(); + jobs.push_back(WorkerJob::new_printer( + "Building VapoR...", + Some(TermColor::Blue), + )); + + let git = Git { + repo: profile + .ovr_comp + .repo + .as_ref() + .unwrap_or(&"https://github.com/micheal65536/VapoR.git".into()) + .clone(), + dir: profile.ovr_comp.path.clone(), + branch: profile + .ovr_comp + .branch + .as_ref() + .unwrap_or(&"master".into()) + .clone(), + }; + + jobs.extend(git.get_pre_build_jobs(profile.pull_on_build)); + + let build_dir = profile.ovr_comp.path.join("build"); + let cmake = Cmake { + env: None, + vars: Some({ + let mut cmake_vars: HashMap = HashMap::new(); + for (k, v) in [ + ("VAPOR_LOG_SILENT=ON", "ON"), + ("CMAKE_BUILD_TYPE", "RelWithDebInfo"), + ] { + cmake_vars.insert(k.to_string(), v.to_string()); + } + cmake_vars + }), + source_dir: profile.ovr_comp.path.clone(), + build_dir: build_dir.clone(), + }; + if !Path::new(&build_dir).is_dir() || clean_build { + rm_rf(&build_dir); + jobs.push_back(cmake.get_prepare_job()); + } + jobs.push_back(cmake.get_build_job()); + jobs.push_back(WorkerJob::Func(FuncWorkerData { + func: Box::new(move || { + let dest_dir = build_dir.join("bin/linux64"); + if let Err(e) = create_dir_all(&dest_dir) { + return FuncWorkerOut { + success: false, + out: vec![format!( + "failed to create dir {}: {e}", + dest_dir.to_string_lossy() + )], + }; + } + copy_file( + &build_dir.join("src/vrclient.so"), + &dest_dir.join("vrclient.so"), + ); + + FuncWorkerOut { + success: true, + out: Vec::default(), + } + }), + })); + + jobs +} diff --git a/src/builders/mod.rs b/src/builders/mod.rs index 1f66748..9d57245 100644 --- a/src/builders/mod.rs +++ b/src/builders/mod.rs @@ -4,5 +4,6 @@ pub mod build_mercury; pub mod build_monado; pub mod build_opencomposite; pub mod build_openhmd; +pub mod build_vapor; pub mod build_wivrn; pub mod build_xrizer; diff --git a/src/profile.rs b/src/profile.rs index ad6b170..7433de9 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -265,6 +265,7 @@ pub enum OvrCompatibilityModuleType { #[default] Opencomposite, Xrizer, + Vapor, } impl Display for OvrCompatibilityModuleType { @@ -272,13 +273,14 @@ impl Display for OvrCompatibilityModuleType { f.write_str(match self { Self::Opencomposite => "OpenComposite", Self::Xrizer => "xrizer", + Self::Vapor => "VapoR", }) } } impl OvrCompatibilityModuleType { pub fn iter() -> Iter<'static, Self> { - [Self::Opencomposite, Self::Xrizer].iter() + [Self::Opencomposite, Self::Xrizer, Self::Vapor].iter() } } @@ -289,6 +291,7 @@ impl FromStr for OvrCompatibilityModuleType { match s.to_lowercase().trim() { "opencomposite" => Ok(Self::Opencomposite), "xrizer" => Ok(Self::Xrizer), + "vapor" => Ok(Self::Vapor), _ => Err(format!("no match for ovr compatibility module `{s}`")), } } @@ -299,7 +302,8 @@ impl From for OvrCompatibilityModuleType { match value { 0 => Self::Opencomposite, 1 => Self::Xrizer, - _ => panic!("OvrCompatibilityModuleType index out of bounds"), + 2 => Self::Vapor, + _ => panic!("OvrCompatibilityModuleType index out of bounds"), } } } @@ -327,7 +331,9 @@ impl ProfileOvrCompatibilityModule { /// this should correspond to the build output directory pub fn runtime_dir(&self) -> PathBuf { match self.mod_type { - OvrCompatibilityModuleType::Opencomposite => self.path.join("build"), + OvrCompatibilityModuleType::Opencomposite | OvrCompatibilityModuleType::Vapor => { + self.path.join("build") + } OvrCompatibilityModuleType::Xrizer => self.path.join("target/release"), } } diff --git a/src/ui/app.rs b/src/ui/app.rs index 5df4dba..9910d2d 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -20,7 +20,8 @@ use crate::{ build_basalt::get_build_basalt_jobs, build_libsurvive::get_build_libsurvive_jobs, build_mercury::get_build_mercury_jobs, build_monado::get_build_monado_jobs, build_opencomposite::get_build_opencomposite_jobs, build_openhmd::get_build_openhmd_jobs, - build_wivrn::get_build_wivrn_jobs, build_xrizer::get_build_xrizer_jobs, + build_vapor::get_build_vapor_jobs, build_wivrn::get_build_wivrn_jobs, + build_xrizer::get_build_xrizer_jobs, }, config::{Config, PluginConfig}, constants::APP_NAME, @@ -533,6 +534,9 @@ impl AsyncComponent for App { OvrCompatibilityModuleType::Xrizer => { get_build_xrizer_jobs(&profile, clean_build) } + OvrCompatibilityModuleType::Vapor => { + get_build_vapor_jobs(&profile, clean_build) + } }); let missing_deps = profile.missing_dependencies(); if !(self.skip_depcheck || profile.skip_dependency_check || missing_deps.is_empty()) From 25c90d175f83e4a4439b4c58e2ce687843ae3c1b Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sun, 6 Apr 2025 13:30:30 +0200 Subject: [PATCH 06/33] chore: clippy --- src/linux_distro.rs | 6 +++--- src/ui/about_dialog.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/linux_distro.rs b/src/linux_distro.rs index 7bdfe0b..14cb0d0 100644 --- a/src/linux_distro.rs +++ b/src/linux_distro.rs @@ -49,13 +49,13 @@ impl LinuxDistro { Ok(_) if buf.starts_with("PRETTY_NAME=\"") => { return buf .split('=') - .last() + .next_back() .map(|b| b.trim().trim_matches('"').trim().to_string()); } Ok(_) if buf.starts_with("NAME=\"") => { name = buf .split('=') - .last() + .next_back() .map(|b| b.trim().trim_matches('"').trim().to_string()); } _ => {} @@ -79,7 +79,7 @@ impl LinuxDistro { { let name = buf .split('=') - .last() + .next_back() .unwrap_or_default() .trim() .trim_matches('"') diff --git a/src/ui/about_dialog.rs b/src/ui/about_dialog.rs index 795d546..0e28534 100644 --- a/src/ui/about_dialog.rs +++ b/src/ui/about_dialog.rs @@ -33,7 +33,7 @@ pub fn create_about_dialog() -> adw::AboutDialog { const UNKNOWN: &str = "UNKNOWN"; pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo>) { - if dialog.debug_info().len() > 0 { + if !dialog.debug_info().is_empty() { return; } let distro_family = LinuxDistro::get(); @@ -70,7 +70,7 @@ pub fn populate_debug_info(dialog: &adw::AboutDialog, vkinfo: Option<&VulkanInfo .and_then(|s| { s.split("\n") .find(|line| line.starts_with("model name")) - .map(|line| line.split(':').last().map(|s| s.trim().to_string())) + .map(|line| line.split(':').next_back().map(|s| s.trim().to_string())) }) .flatten() .unwrap_or(UNKNOWN.into()) From 8742a27b7c61c4e3f4fbf7f45188868a9a7dae73 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Mon, 7 Apr 2025 08:12:08 +0200 Subject: [PATCH 07/33] feat: small design changes to build window ui --- src/ui/build_window.rs | 57 +++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/ui/build_window.rs b/src/ui/build_window.rs index 759af9b..7b0ac69 100644 --- a/src/ui/build_window.rs +++ b/src/ui/build_window.rs @@ -88,43 +88,54 @@ impl SimpleComponent for BuildWindow { gtk::Label { #[track = "model.changed(BuildWindow::build_status())"] set_markup: match &model.build_status { - BuildStatus::Building => "Build in progress...".to_string(), - BuildStatus::Done => "Build done, you can close this window".to_string(), + BuildStatus::Building => String::default(), + BuildStatus::Done => "Build done, you can close this window".into(), BuildStatus::Error(code) => { format!("Build failed: \"{c}\"", c = code) } }.as_str(), + #[track = "model.changed(BuildWindow::build_status())"] + set_visible: match &model.build_status { + BuildStatus::Building => false, + BuildStatus::Done | BuildStatus::Error(_) => true, + }, add_css_class: "title-2", set_wrap: true, set_wrap_mode: gtk::pango::WrapMode::Word, set_justify: gtk::Justification::Center, }, - gtk::Button { - #[track = "model.changed(BuildWindow::build_status())"] - set_visible: matches!(&model.build_status, BuildStatus::Building), - add_css_class: "destructive-action", - add_css_class: "circular", - set_icon_name: "window-close-symbolic", - set_tooltip_text: Some("Cancel build"), - connect_clicked[sender] => move |_| { - sender.output(Self::Output::CancelBuild).expect(SENDER_IO_ERR_MSG); - } - }, }, model.term.container.clone(), }, - add_bottom_bar: bottom_bar = >k::Button { - add_css_class: "pill", + add_bottom_bar: bottom_bar = >k::Box { + set_orientation: gtk::Orientation::Horizontal, set_halign: gtk::Align::Center, - set_label: "Close", - set_margin_all: 12, - #[track = "model.changed(BuildWindow::can_close())"] - set_sensitive: model.can_close, - connect_clicked[win] => move |_| { - - win.close(); + set_hexpand: true, + set_margin_bottom: 24, + set_spacing: 12, + gtk::Button { + add_css_class: "pill", + set_halign: gtk::Align::Center, + set_label: "Close", + #[track = "model.changed(BuildWindow::can_close())"] + set_visible: model.can_close, + connect_clicked[win] => move |_| { + win.close(); + }, }, - } + // this + gtk::Button { + #[track = "model.changed(BuildWindow::build_status())"] + set_visible: matches!(&model.build_status, BuildStatus::Building), + add_css_class: "destructive-action", + add_css_class: "pill", + set_label: "Cancel build", + connect_clicked[sender] => move |_| { + sender.output(Self::Output::CancelBuild).expect(SENDER_IO_ERR_MSG); + } + }, + // ^^^ + }, } } } From 2f5ec57a0a95bdf889094d459a4a3fcb4de2dd97 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Mon, 7 Apr 2025 08:00:35 +0200 Subject: [PATCH 08/33] feat: don't set openvrpaths as read only during profile startup --- src/file_builders/openvrpaths_vrpath.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/file_builders/openvrpaths_vrpath.rs b/src/file_builders/openvrpaths_vrpath.rs index 7bd431b..1b888c2 100644 --- a/src/file_builders/openvrpaths_vrpath.rs +++ b/src/file_builders/openvrpaths_vrpath.rs @@ -85,6 +85,7 @@ fn build_steam_openvrpaths() -> OpenVrPaths { } pub fn set_current_openvrpaths_to_steam() -> anyhow::Result<()> { + // removing readonly flag just in case, remove this line in the future set_file_readonly(&get_openvrpaths_vrpath_path(), false)?; dump_current_openvrpaths(&build_steam_openvrpaths())?; Ok(()) @@ -104,18 +105,17 @@ pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths { pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<()> { let dest = get_openvrpaths_vrpath_path(); + // removing readonly flag just in case, remove this line in the future set_file_readonly(&dest, false)?; backup_steam_openvrpaths(); dump_current_openvrpaths(&build_profile_openvrpaths(profile))?; - set_file_readonly(&dest, true)?; Ok(()) } #[cfg(test)] mod tests { - use std::path::Path; - use super::{dump_openvrpaths_to_path, get_openvrpaths_from_path, OpenVrPaths}; + use std::path::Path; #[test] fn can_read_openvrpaths_vrpath_steamvr() { From 7a02fcc5d109d2d06bb115f93811424bd88343aa Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 8 Apr 2025 15:38:20 +0200 Subject: [PATCH 09/33] fix: disable and blacklist wayvr dashboard plugin --- src/ui/app.rs | 4 ++++ src/ui/plugins/mod.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ui/app.rs b/src/ui/app.rs index 9910d2d..7354cdc 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -249,6 +249,10 @@ impl App { .plugins .values() .filter_map(|cp| { + // disable potentially unsafe wayvr_dashboard + if cp.plugin.appid.contains("wayvr_dashboard") { + return None; + } if cp.enabled && cp.plugin.validate() { if let Err(e) = cp.plugin.mark_as_executable() { error!( diff --git a/src/ui/plugins/mod.rs b/src/ui/plugins/mod.rs index 8d2d792..7dcabd1 100644 --- a/src/ui/plugins/mod.rs +++ b/src/ui/plugins/mod.rs @@ -163,10 +163,10 @@ impl Plugin { /// urls to manifest json files representing plugins. /// each manifest should be json and the link should always point to the latest version -const MANIFESTS: [&str;3] = [ +const MANIFESTS: [&str;2] = [ "https://github.com/galister/wlx-overlay-s/raw/refs/heads/meta/com.github.galister.wlx-overlay-s.json", - "https://github.com/olekolek1000/wayvr-dashboard/raw/refs/heads/meta/dev.oo8.wayvr_dashboard.json", "https://github.com/StardustXR/telescope/raw/refs/heads/main/envision/org.stardustxr.telescope.json", + // wayvr dashboard potentially unsafe ]; pub async fn refresh_plugins() -> anyhow::Result>> { From 139f72e2941c4e91091acef6c86712fec566425b Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 8 Apr 2025 15:49:55 +0200 Subject: [PATCH 10/33] chore: update version to 3.1.0 --- Cargo.toml | 2 +- data/org.gabmus.envision.metainfo.xml.in.in | 20 ++++++++++++++++++++ meson.build | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 575b302..600ce85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "envision" -version = "3.0.1" +version = "3.1.0" edition = "2021" authors = [ "Gabriele Musco ", diff --git a/data/org.gabmus.envision.metainfo.xml.in.in b/data/org.gabmus.envision.metainfo.xml.in.in index 8925605..2584ddb 100644 --- a/data/org.gabmus.envision.metainfo.xml.in.in +++ b/data/org.gabmus.envision.metainfo.xml.in.in @@ -30,6 +30,26 @@ @REPO_URL@/issues + + +

What's new

+
    +
  • don't set openvrpaths as read only during profile startup
  • +
  • small design changes to build window ui
  • +
  • add support for vapor openvr compatibility module
  • +
  • remove monado vulkan layers check for nvidia
  • +
+

Fixes

+
    +
  • disable and blacklist wayvr dashboard plugin
  • +
  • monado dependencies: use wayland-protocols-devel on Fedora
  • +
+

Other changes

+
    +
  • clippy
  • +
+
+

Fixes

diff --git a/meson.build b/meson.build index 7e406b2..25b7ecc 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'envision', 'rust', - version: '3.0.1', # version number row + version: '3.1.0', # version number row meson_version: '>= 0.59', license: 'AGPL-3.0-or-later', ) From 9ea754bb2e1b94dac333c423c28234ccfcfc5a08 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Sun, 13 Apr 2025 19:59:15 +0200 Subject: [PATCH 11/33] fix: Revert "disable and blacklist wayvr dashboard plugin" --- src/ui/app.rs | 4 ---- src/ui/plugins/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ui/app.rs b/src/ui/app.rs index 7354cdc..9910d2d 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -249,10 +249,6 @@ impl App { .plugins .values() .filter_map(|cp| { - // disable potentially unsafe wayvr_dashboard - if cp.plugin.appid.contains("wayvr_dashboard") { - return None; - } if cp.enabled && cp.plugin.validate() { if let Err(e) = cp.plugin.mark_as_executable() { error!( diff --git a/src/ui/plugins/mod.rs b/src/ui/plugins/mod.rs index 7dcabd1..cb18440 100644 --- a/src/ui/plugins/mod.rs +++ b/src/ui/plugins/mod.rs @@ -163,10 +163,10 @@ impl Plugin { /// urls to manifest json files representing plugins. /// each manifest should be json and the link should always point to the latest version -const MANIFESTS: [&str;2] = [ +const MANIFESTS: [&str;3] = [ "https://github.com/galister/wlx-overlay-s/raw/refs/heads/meta/com.github.galister.wlx-overlay-s.json", "https://github.com/StardustXR/telescope/raw/refs/heads/main/envision/org.stardustxr.telescope.json", - // wayvr dashboard potentially unsafe + "https://github.com/olekolek1000/wayvr-dashboard/raw/refs/heads/meta/dev.oo8.wayvr_dashboard.json", ]; pub async fn refresh_plugins() -> anyhow::Result>> { From e4d3980b1496df67ff456413bba48dcebc15ce9c Mon Sep 17 00:00:00 2001 From: Sapphire Date: Wed, 9 Apr 2025 23:42:24 -0500 Subject: [PATCH 12/33] fix: add libusb and libusb-dev deps --- src/depcheck/monado_deps.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index 8c555fc..5d98ebf 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -87,6 +87,30 @@ fn monado_deps() -> Vec { ]), }, dep_libudev(), + Dependency { + name: "libusb".into(), + dep_type: DepType::SharedObject, + filename: "libusb-1.0.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "libusb".into()), + (LinuxDistro::Debian, "libusb-1.0-0".into()), + (LinuxDistro::Fedora, "libusb1".into()), + (LinuxDistro::Gentoo, "dev-libs/libusb".into()), + (LinuxDistro::Suse, "libusb-1_0".into()), + ]), + }, + Dependency { + name: "libusb-dev".into(), + dep_type: DepType::Include, + filename: "libusb-1.0/libusb.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "libusb".into()), + (LinuxDistro::Debian, "libusb-1.0-0-dev".into()), + (LinuxDistro::Fedora, "libusb1-devel".into()), + (LinuxDistro::Gentoo, "dev-libs/libusb".into()), + (LinuxDistro::Suse, "libusb-1_0-devel".into()), + ]), + }, Dependency { name: "mesa-common-dev".into(), dep_type: DepType::Include, From 71a8223ce8b95fa6f37e6aa465044a5665056ef3 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 22 Apr 2025 08:14:23 +0200 Subject: [PATCH 13/33] chore: update version to 3.1.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- data/org.gabmus.envision.metainfo.xml.in.in | 9 +++++++++ meson.build | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc56ea6..74138cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,7 +563,7 @@ dependencies = [ [[package]] name = "envision" -version = "3.0.1" +version = "3.1.1" dependencies = [ "anyhow", "ash", diff --git a/Cargo.toml b/Cargo.toml index 600ce85..62cf1dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "envision" -version = "3.1.0" +version = "3.1.1" edition = "2021" authors = [ "Gabriele Musco ", diff --git a/data/org.gabmus.envision.metainfo.xml.in.in b/data/org.gabmus.envision.metainfo.xml.in.in index 2584ddb..76b4dd4 100644 --- a/data/org.gabmus.envision.metainfo.xml.in.in +++ b/data/org.gabmus.envision.metainfo.xml.in.in @@ -30,6 +30,15 @@ @REPO_URL@/issues + + +

Fixes

+
    +
  • add libusb and libusb-dev deps
  • +
  • Revert "disable and blacklist wayvr dashboard plugin"
  • +
+
+

What's new

diff --git a/meson.build b/meson.build index 25b7ecc..d58f4ed 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'envision', 'rust', - version: '3.1.0', # version number row + version: '3.1.1', # version number row meson_version: '>= 0.59', license: 'AGPL-3.0-or-later', ) From 3e23073f4cb025e69d64b2be05c61d7091f3e41b Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 22 Apr 2025 09:01:00 +0200 Subject: [PATCH 14/33] feat: remove old logs on startup, keep a max of 1GB and 3 files --- src/main.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index bb72425..217434e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,9 +11,14 @@ use relm4::{ gtk::{self, gdk, gio, glib, prelude::*}, MessageBroker, RelmApp, }; -use std::env; +use std::{ + env, + fs::{read_dir, remove_file}, + os::unix::fs::MetadataExt, + path::{Path, PathBuf}, +}; use steam_linux_runtime_injector::restore_runtime_entrypoint; -use tracing::warn; +use tracing::{error, warn}; use tracing_subscriber::{ filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, }; @@ -66,11 +71,55 @@ fn restore_steam_xr_files() { restore_runtime_entrypoint(); } +const LOGS_MAX_SIZE_BYTES: u64 = 1000000000; // 1GB + +fn remove_old_logs(dir: &Path, log_files: Option>) -> anyhow::Result<()> { + let log_files: Vec = log_files + .map::>, _>(Ok) + .unwrap_or_else(|| { + let mut files: Vec = read_dir(dir)? + .filter_map(|de| { + let p = de.ok()?.path(); + if p.is_file() && !p.is_symlink() { + Some(p) + } else { + None + } + }) + .collect(); + files.sort_unstable(); + Ok(files) + })?; + let total_size = log_files + .iter() + .filter_map(|p| Some(p.metadata().ok()?.size())) + .reduce(u64::saturating_add) + .unwrap_or(0); + // if size is under threshold, finish + if total_size < LOGS_MAX_SIZE_BYTES { + return Ok(()); + } + // keep a minimum of 3 logs + if log_files.len() <= 3 { + return Ok(()); + } + + remove_file(log_files.first().ok_or_else(|| + anyhow::Error::msg( + "Could not get first item in log files list, but they should be more than 3! This is a bug!" + ) + )?)?; + + remove_old_logs(dir, Some(log_files)) +} + fn main() -> Result<()> { if env::var("USER").unwrap_or_else(|_| env::var("USERNAME").unwrap_or_default()) == "root" { panic!("{APP_NAME} cannot run as root"); } restore_steam_xr_files(); + // deferring error logging for this since tracing isn't initialized yet + let old_logs_removal_res = remove_old_logs(&get_logs_dir(), None); let rolling_log_writer = tracing_appender::rolling::daily(get_logs_dir(), "log"); let (non_blocking_appender, _appender_guard) = @@ -90,6 +139,10 @@ fn main() -> Result<()> { ) .init(); + if let Err(e) = old_logs_removal_res { + error!("Failed to remove old log files: {e}"); + } + // Prepare i18n gettextrs::setlocale(LocaleCategory::LcAll, ""); gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR).expect("Unable to bind the text domain"); From 9d85f1c24f5c6234e1672c96ea19b2dc990001e8 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 22 Apr 2025 09:04:13 +0200 Subject: [PATCH 15/33] fix: remove 2 thread limit when building basalt --- src/builders/build_basalt.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/builders/build_basalt.rs b/src/builders/build_basalt.rs index 10d6029..0d8130f 100644 --- a/src/builders/build_basalt.rs +++ b/src/builders/build_basalt.rs @@ -40,7 +40,6 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque = HashMap::new(); for (k, v) in [ - ("CMAKE_BUILD_PARALLEL_LEVEL", "2"), ("CMAKE_BUILD_TYPE", "RelWithDebInfo"), ("BUILD_TESTS", "off"), ] { From c794037377bbddc014ce4a58b3662038fc6b056f Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Tue, 29 Apr 2025 14:22:27 +0200 Subject: [PATCH 16/33] feat: checkbox to delete profile dirs along with profile --- src/profile.rs | 25 ++++++++++++++++++++++++- src/ui/app.rs | 14 +++++++++++--- src/ui/main_view.rs | 23 ++++++++++++++++++++--- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/profile.rs b/src/profile.rs index 7433de9..a3344df 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, fmt::Display, - fs::File, + fs::{remove_dir_all, File}, io::BufReader, path::{Path, PathBuf}, slice::Iter, @@ -450,6 +450,29 @@ impl Profile { get_data_dir().join("prefixes").join(uuid) } + /// deletes files and folders associated to this profile (mostly repo clones) + pub fn delete_files(&self) -> Vec> { + [ + Some(&self.xrservice_path), + Some(&self.ovr_comp.path), + self.features.libsurvive.path.as_ref(), + self.features.basalt.path.as_ref(), + self.features.openhmd.path.as_ref(), + ] + .iter() + .map(|dir| match dir { + Some(dir) => { + if dir.try_exists().unwrap_or_default() { + remove_dir_all(dir) + } else { + Ok(()) + } + } + None => Ok(()), + }) + .collect() + } + pub fn xr_runtime_json_env_var(&self) -> String { format!( "XR_RUNTIME_JSON=\"{prefix}/share/openxr/1/openxr_{runtime}.json\"", diff --git a/src/ui/app.rs b/src/ui/app.rs index 9910d2d..c4f3b10 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -113,7 +113,8 @@ pub enum Msg { StartWithDebug, RestartXRService, ProfileSelected(Profile), - DeleteProfile, + /// bool param: delete files + DeleteProfile(bool), SaveProfile(Profile), RunSetCap, OpenLibsurviveSetup, @@ -658,9 +659,16 @@ impl AsyncComponent for App { w.stop(); } } - Msg::DeleteProfile => { + Msg::DeleteProfile(delete_files) => { let todel = self.get_selected_profile(); if todel.editable { + if delete_files { + for res in todel.delete_files() { + if let Err(e) = res { + error!("Error deleting profile directory: {e}"); + } + } + } self.config.user_profiles.retain(|p| p.uuid != todel.uuid); self.config.save(); self.profiles = self.config.profiles(); @@ -1007,7 +1015,7 @@ impl AsyncComponent for App { MainViewOutMsg::DoStartStopXRService => Msg::DoStartStopXRService, MainViewOutMsg::RestartXRService => Msg::RestartXRService, MainViewOutMsg::ProfileSelected(uuid) => Msg::ProfileSelected(uuid), - MainViewOutMsg::DeleteProfile => Msg::DeleteProfile, + MainViewOutMsg::DeleteProfile(delete_files) => Msg::DeleteProfile(delete_files), MainViewOutMsg::SaveProfile(p) => Msg::SaveProfile(p), MainViewOutMsg::OpenLibsurviveSetup => Msg::OpenLibsurviveSetup, MainViewOutMsg::BuildProfile(clean) => Msg::BuildProfile(clean), diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index ce5f7a6..09cd408 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -112,7 +112,8 @@ pub enum MainViewOutMsg { DoStartStopXRService, RestartXRService, ProfileSelected(Profile), - DeleteProfile, + /// bool param: delete files + DeleteProfile(bool), SaveProfile(Profile), OpenLibsurviveSetup, /// params: clean @@ -931,6 +932,13 @@ impl AsyncComponent for MainView { let profile_delete_confirm_dialog = adw::AlertDialog::builder() .heading("Are you sure you want to delete this profile?") + .extra_child( + >k::CheckButton::builder() + .label("Delete all files and folders associated with profile") + .halign(gtk::Align::Center) + .hexpand(true) + .build(), + ) .build(); profile_delete_confirm_dialog.add_response("no", "_No"); profile_delete_confirm_dialog.add_response("yes", "_Yes"); @@ -942,10 +950,19 @@ impl AsyncComponent for MainView { clone!( #[strong] sender, - move |_, res| { + move |dialog, res| { + let delete_files_checkbox = dialog + .extra_child() + .and_then(|child| child.downcast::().ok()); + let delete_files = delete_files_checkbox + .as_ref() + .is_some_and(|c| c.is_active()); + if let Some(check) = delete_files_checkbox { + check.set_active(false); + } if res == "yes" { sender - .output(Self::Output::DeleteProfile) + .output(Self::Output::DeleteProfile(delete_files)) .expect("Sender output failed"); } } From 8ffac63e7e4a540cb9afaf54e15cafc613a6001e Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Fri, 2 May 2025 09:18:54 +0200 Subject: [PATCH 17/33] fix: account for opi packages for opensuse --- src/linux_distro.rs | 62 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/linux_distro.rs b/src/linux_distro.rs index 14cb0d0..d08c71b 100644 --- a/src/linux_distro.rs +++ b/src/linux_distro.rs @@ -150,7 +150,33 @@ impl LinuxDistro { Self::Alpine => format!("sudo apk add {}", packages.join(" ")), Self::Debian => format!("sudo apt install {}", packages.join(" ")), Self::Gentoo => format!("sudo emerge -av {}", packages.join(" ")), - Self::Suse => format!("sudo zypper install {}", packages.join(" ")), + Self::Suse => { + let mut opi_pkgs = Vec::new(); + let mut zypper_pkgs = Vec::new(); + for pkg in packages { + if ["OpenXR-SDK-devel"].contains(&pkg.as_str()) { + opi_pkgs.push(pkg.clone()); + } else { + zypper_pkgs.push(pkg.clone()); + } + } + [ + if opi_pkgs.is_empty() { + None + } else { + Some(format!("opi {}", opi_pkgs.join(" "))) + }, + if zypper_pkgs.is_empty() { + None + } else { + Some(format!("sudo zypper install {}", zypper_pkgs.join(" "))) + }, + ] + .iter() + .filter_map(|c| c.clone()) + .collect::>() + .join(" && ") + } Self::Fedora => { let mut install_rpmfusion_cmd: Option = None; let mut swap_ffmpeg_cmd: Option = None; @@ -190,9 +216,9 @@ impl LinuxDistro { #[cfg(test)] mod tests { - use std::path::Path; - use super::LinuxDistro; + use crate::depcheck::common::{dep_openxr, dep_pkexec, dep_vulkan_icd_loader}; + use std::path::Path; #[test] fn can_detect_arch_linux_from_etc_os_release() { @@ -203,4 +229,34 @@ mod tests { Some(LinuxDistro::Arch) ) } + + #[test] + fn can_account_for_opensuse_opi_packages() { + assert_eq!( + LinuxDistro::Suse + .install_command( + &[dep_openxr(), dep_vulkan_icd_loader()] + .iter() + .map(|dep| dep.package_name_for_distro(Some(&LinuxDistro::Suse))) + .collect::>() + ) + .as_str(), + "opi OpenXR-SDK-devel && sudo zypper install vulkan-devel" + ) + } + + #[test] + fn opensuse_opi_does_not_interfere_if_not_needed() { + assert_eq!( + LinuxDistro::Suse + .install_command( + &[dep_pkexec(), dep_vulkan_icd_loader()] + .iter() + .map(|dep| dep.package_name_for_distro(Some(&LinuxDistro::Suse))) + .collect::>() + ) + .as_str(), + "sudo zypper install polkit vulkan-devel" + ) + } } From 743dbfa3a17c79493cd2df1c36187a560ec9c3d6 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Fri, 2 May 2025 09:35:35 +0200 Subject: [PATCH 18/33] feat: account for getcap/setcap being found in /sbin and not in $PATH --- src/depcheck/common.rs | 16 ++++++++++++ src/util/file_utils.rs | 59 ++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/depcheck/common.rs b/src/depcheck/common.rs index 56ac4ef..dcae582 100644 --- a/src/depcheck/common.rs +++ b/src/depcheck/common.rs @@ -303,3 +303,19 @@ pub fn dep_adb() -> Dependency { ]), } } + +pub fn dep_getcap_setcap() -> Dependency { + Dependency { + name: "libcap".into(), + dep_type: DepType::Executable, + filename: "setcap".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "libcap".into()), + (LinuxDistro::Debian, "libcap2-bin".into()), + (LinuxDistro::Fedora, "libcap".into()), + (LinuxDistro::Alpine, "libcap".into()), + (LinuxDistro::Gentoo, "sys-libs/libcap".into()), + (LinuxDistro::Suse, "libcap-progs".into()), + ]), + } +} diff --git a/src/util/file_utils.rs b/src/util/file_utils.rs index ff56926..04efb13 100644 --- a/src/util/file_utils.rs +++ b/src/util/file_utils.rs @@ -1,4 +1,4 @@ -use crate::{async_process::async_process, profile::Profile}; +use crate::{async_process::async_process, depcheck::common::dep_getcap_setcap, profile::Profile}; use anyhow::bail; use nix::{ errno::Errno, @@ -79,9 +79,29 @@ pub fn set_file_readonly(path: &Path, readonly: bool) -> anyhow::Result<()> { Ok(fs::set_permissions(path, perms)?) } +pub fn setcap_executable() -> Option { + if dep_getcap_setcap().check() { + Some("setcap".into()) + } else if Path::new("/sbin/setcap").try_exists().unwrap_or_default() { + Some("/sbin/setcap".into()) + } else { + None + } +} + +pub fn getcap_executable() -> Option { + if dep_getcap_setcap().check() { + Some("getcap".into()) + } else if Path::new("/sbin/getcap").try_exists().unwrap_or_default() { + Some("/sbin/getcap".into()) + } else { + None + } +} + pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec { vec![ - "setcap".into(), + setcap_executable().unwrap_or("setcap".into()), "CAP_SYS_NICE=eip".into(), profile .prefix @@ -93,24 +113,29 @@ pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec { pub async fn verify_cap_sys_nice_eip(profile: &Profile) -> bool { let xrservice_binary = profile.xrservice_binary().to_string_lossy().to_string(); - match async_process("getcap", Some(&[&xrservice_binary]), None).await { - Err(e) => { - error!("failed to run `getcap {xrservice_binary}`: {e:?}"); - false - } - Ok(out) => { - debug!("getcap {xrservice_binary} stdout: {}", out.stdout); - debug!("getcap {xrservice_binary} stderr: {}", out.stderr); - if out.exit_code != 0 { - error!( - "command `getcap {xrservice_binary}` failed with status code {}", - out.exit_code - ); + if let Some(getcap_exec) = getcap_executable() { + match async_process(&getcap_exec, Some(&[&xrservice_binary]), None).await { + Err(e) => { + error!("failed to run `getcap {xrservice_binary}`: {e:?}"); false - } else { - out.stdout.to_lowercase().contains("cap_sys_nice=eip") + } + Ok(out) => { + debug!("getcap {xrservice_binary} stdout: {}", out.stdout); + debug!("getcap {xrservice_binary} stderr: {}", out.stderr); + if out.exit_code != 0 { + error!( + "command `getcap {xrservice_binary}` failed with status code {}", + out.exit_code + ); + false + } else { + out.stdout.to_lowercase().contains("cap_sys_nice=eip") + } } } + } else { + error!("getcap executable does not exist"); + false } } From e0eae7c13a1fa699642f1361277f2ae1fc84abdf Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Thu, 1 May 2025 01:18:46 +0200 Subject: [PATCH 19/33] feat: theme manager --- Cargo.lock | 23 ++++++++++++++------ Cargo.toml | 1 + src/config.rs | 7 +++++++ src/ui/app.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++- src/ui/main_view.rs | 2 ++ 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74138cb..cb2d639 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "delicious-adwaita" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53548c789a95211e0ce6d26c213067002b9b4360f8de69046d84de78ad9da3f" +dependencies = [ + "gtk4", + "libadwaita", +] + [[package]] name = "deranged" version = "0.3.11" @@ -567,6 +577,7 @@ version = "3.1.1" dependencies = [ "anyhow", "ash", + "delicious-adwaita", "gettext-rs", "git2", "gtk4", @@ -1073,9 +1084,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9376d14d7e33486c54823a42bef296e882b9f25cb4c52b52f4d1d57bbadb5b6d" +checksum = "af1c491051f030994fd0cde6f3c44f3f5640210308cff1298c7673c47408091d" dependencies = [ "cairo-rs", "field-offset", @@ -1106,9 +1117,9 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e653b0a9001ba9be1ffddb9373bfe9a111f688222f5aeee2841481300d91b55a" +checksum = "41e03b01e54d77c310e1d98647d73f996d04b2f29b9121fe493ea525a7ec03d6" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1523,9 +1534,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libadwaita" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8611ee9fb85e7606c362b513afcaf5b59853f79e4d98caaaf581d99465014247" +checksum = "500135d29c16aabf67baafd3e7741d48e8b8978ca98bac39e589165c8dc78191" dependencies = [ "gdk4", "gio", diff --git a/Cargo.toml b/Cargo.toml index 62cf1dc..4ecd109 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,3 +44,4 @@ tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] } tracing = "0.1.41" tracing-appender = "0.2.3" serde_yaml = "0.9.34" +delicious-adwaita = { version = "0.3.0", features = ["all_themes"] } diff --git a/src/config.rs b/src/config.rs index 18cd864..80cf0f5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -45,6 +45,10 @@ const fn default_win_size() -> [i32; 2] { DEFAULT_WIN_SIZE } +fn default_theme_name() -> String { + "Follow system".into() +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Config { pub selected_profile_uuid: String, @@ -54,6 +58,8 @@ pub struct Config { pub win_size: [i32; 2], #[serde(default)] pub plugins: HashMap, + #[serde(default = "default_theme_name")] + pub theme_name: String, } impl Default for Config { @@ -65,6 +71,7 @@ impl Default for Config { user_profiles: Vec::default(), win_size: DEFAULT_WIN_SIZE, plugins: HashMap::default(), + theme_name: default_theme_name(), } } } diff --git a/src/ui/app.rs b/src/ui/app.rs index c4f3b10..4cc6520 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -51,6 +51,7 @@ use crate::{ xr_devices::XRDevice, }; use adw::{prelude::*, ResponseAppearance}; +use delicious_adwaita::{theme::Theme, ThemeEngine}; use gtk::glib::{self, clone}; use notify_rust::NotificationHandle; use relm4::{ @@ -96,6 +97,8 @@ pub struct App { inhibit_fail_notif: Option, pluginstore: Option>, + + theme_engine: ThemeEngine, } #[derive(Debug)] @@ -130,6 +133,8 @@ pub enum Msg { WivrnCheckPairMode, OpenPluginStore, UpdateConfigPlugins(HashMap), + ShowThemeManager, + SaveThemeConfig, NoOp, } @@ -367,7 +372,7 @@ impl AsyncComponent for App { set_content: Some(&adw::NavigationPage::new(model.debug_view.widget(), "Debug View")), set_show_content: false, set_collapsed: !model.config.debug_view_enabled, - } + }, }, connect_close_request[sender] => move |win| { sender.input(Msg::SaveWinSize(win.width(), win.height())); @@ -391,6 +396,27 @@ impl AsyncComponent for App { ) { match message { Msg::NoOp => {} + Msg::ShowThemeManager => { + let dialog = self + .theme_engine + .theme_chooser_dialog(Theme::default_themes().as_ref()); + dialog.set_content_height(2000); + dialog.present(Some(&self.app_win)); + dialog.connect_closed(clone!( + #[strong] + sender, + move |_| { + sender.input(Msg::SaveThemeConfig); + } + )); + } + Msg::SaveThemeConfig => { + let name = self.theme_engine.current_theme_name(); + if self.config.theme_name != name { + self.config.theme_name = name; + self.config.save(); + } + } Msg::OnServiceLog(rows) => { if !rows.is_empty() { self.debug_view @@ -974,6 +1000,17 @@ impl AsyncComponent for App { } ) ); + stateless_action!( + actions, + ThemeManagerAction, + clone!( + #[strong] + sender, + move |_| { + sender.input(Msg::ShowThemeManager); + } + ) + ); // this bypasses the macro because I need the underlying gio action // to enable/disable it in update() let configure_wivrn_action = { @@ -1042,6 +1079,17 @@ impl AsyncComponent for App { .detach(), split_view: None, setcap_confirm_dialog, + theme_engine: ThemeEngine::new_with_theme(&{ + if config.theme_name == "Follow system" { + Theme::default() + } else { + Theme::default_themes() + .into_iter() + .find(|t| t.name == config.theme_name) + .unwrap_or_default() + } + }) + .unwrap(), config, profiles, xrservice_worker: None, @@ -1130,6 +1178,7 @@ new_stateless_action!(pub QuitAction, AppActionGroup, "quit"); new_stateful_action!(pub DebugViewToggleAction, AppActionGroup, "debugviewtoggle", (), bool); new_stateless_action!(pub ConfigureWivrnAction, AppActionGroup, "configurewivrn"); new_stateless_action!(pub PluginStoreAction, AppActionGroup, "store"); +new_stateless_action!(pub ThemeManagerAction, AppActionGroup, "thememanager"); new_stateless_action!(pub DebugOpenDataAction, AppActionGroup, "debugopendata"); new_stateless_action!(pub DebugOpenPrefixAction, AppActionGroup, "debugopenprefix"); diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index 09cd408..8a2c145 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -21,6 +21,7 @@ use crate::{ paths::{get_data_dir, get_home_dir}, profile::{LighthouseDriver, Profile, XRServiceType}, stateless_action, + ui::app::ThemeManagerAction, util::{ file_utils::{get_writer, mount_has_nosuid}, steamvr_utils::chaperone_info_exists, @@ -159,6 +160,7 @@ impl AsyncComponent for MainView { "Configure _WiVRn" => ConfigureWivrnAction, }, section! { + "Change _Theme" => ThemeManagerAction, "_About" => AboutAction, }, }, From 99af59056d2f33baea201474bde28de4f9b0674b Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Fri, 2 May 2025 11:14:11 +0200 Subject: [PATCH 20/33] fix: opensuse dep SDL2-devel is now sdl2-compat-devel --- src/depcheck/monado_deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index 5d98ebf..e962b89 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -83,7 +83,7 @@ fn monado_deps() -> Vec { (LinuxDistro::Debian, "libsdl2-dev".into()), (LinuxDistro::Fedora, "SDL2-devel".into()), (LinuxDistro::Gentoo, "media-libs/libsdl2".into()), - (LinuxDistro::Suse, "SDL2-devel".into()), + (LinuxDistro::Suse, "sdl2-compat-devel".into()), ]), }, dep_libudev(), From d0df943e483f1c768eb35ad60f06a7854e1b3a91 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Fri, 2 May 2025 11:16:49 +0200 Subject: [PATCH 21/33] fix: opensuse dep libusb-1_0 is now libusb-1_0-0 --- src/depcheck/monado_deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index e962b89..b4894da 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -96,7 +96,7 @@ fn monado_deps() -> Vec { (LinuxDistro::Debian, "libusb-1.0-0".into()), (LinuxDistro::Fedora, "libusb1".into()), (LinuxDistro::Gentoo, "dev-libs/libusb".into()), - (LinuxDistro::Suse, "libusb-1_0".into()), + (LinuxDistro::Suse, "libusb-1_0-0".into()), ]), }, Dependency { From 4709a50483b44a3fe1638da209eab9d09e3184ea Mon Sep 17 00:00:00 2001 From: Sapphire Date: Mon, 5 May 2025 00:12:42 -0500 Subject: [PATCH 22/33] fix: xrizer deps --- src/depcheck/mod.rs | 1 + src/depcheck/xrizer_deps.rs | 57 +++++++++++++++++++++++++++++++++++++ src/profile.rs | 14 +++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/depcheck/xrizer_deps.rs diff --git a/src/depcheck/mod.rs b/src/depcheck/mod.rs index 002a8c8..e46b1e7 100644 --- a/src/depcheck/mod.rs +++ b/src/depcheck/mod.rs @@ -6,6 +6,7 @@ pub mod mercury_deps; pub mod monado_deps; pub mod openhmd_deps; pub mod wivrn_deps; +pub mod xrizer_deps; use crate::linux_distro::LinuxDistro; use std::{collections::HashMap, env, fmt::Display, path::Path}; diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs new file mode 100644 index 0000000..ec48b4b --- /dev/null +++ b/src/depcheck/xrizer_deps.rs @@ -0,0 +1,57 @@ +use super::{DepType, Dependency, DependencyCheckResult}; +use crate::linux_distro::LinuxDistro; +use std::collections::HashMap; + +fn xrizer_deps() -> Vec { + vec![ + Dependency { + name: "glslc".into(), + dep_type: DepType::Executable, + filename: "glslc".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "shaderc".into()), + (LinuxDistro::Debian, "glslc".into()), + (LinuxDistro::Fedora, "glslc".into()), + (LinuxDistro::Alpine, "glslc".into()), + (LinuxDistro::Gentoo, "dev-util/glslang".into()), + (LinuxDistro::Suse, "shaderc".into()), + ]), + }, + Dependency { + name: "libxcb-glx".into(), + dep_type: DepType::Include, + filename: "xcb/glx.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "libxcb".into()), + (LinuxDistro::Debian, "libxcb-glx0-dev".into()), + (LinuxDistro::Fedora, "libxcb-devel".into()), + (LinuxDistro::Gentoo, "x11-libs/libxcb".into()), + (LinuxDistro::Suse, "libxcb-devel".into()), + ]), + }, + Dependency { + name: "libclang".into(), + dep_type: DepType::SharedObject, + filename: "libclang.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "clang".into()), + (LinuxDistro::Debian, "libclang-19-dev".into()), + (LinuxDistro::Fedora, "clang19-devel".into()), + (LinuxDistro::Gentoo, "llvm-core/clang-runtime".into()), + (LinuxDistro::Suse, "clang19-devel".into()), + ]), + }, + ] +} + +pub fn check_xrizer_deps() -> Vec { + Dependency::check_many(xrizer_deps()) +} + +pub fn get_missing_xrizer_deps() -> Vec { + check_xrizer_deps() + .iter() + .filter(|res| !res.found) + .map(|res| res.dependency.clone()) + .collect() +} diff --git a/src/profile.rs b/src/profile.rs index a3344df..a8cb283 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -2,7 +2,8 @@ use crate::{ depcheck::{ basalt_deps::get_missing_basalt_deps, libsurvive_deps::get_missing_libsurvive_deps, mercury_deps::get_missing_mercury_deps, monado_deps::get_missing_monado_deps, - openhmd_deps::get_missing_openhmd_deps, wivrn_deps::get_missing_wivrn_deps, Dependency, + openhmd_deps::get_missing_openhmd_deps, wivrn_deps::get_missing_wivrn_deps, + xrizer_deps::get_missing_xrizer_deps, Dependency, }, file_builders::active_runtime_json::ActiveRuntime, paths::{get_data_dir, BWRAP_SYSTEM_PREFIX, SYSTEM_PREFIX}, @@ -282,6 +283,15 @@ impl OvrCompatibilityModuleType { pub fn iter() -> Iter<'static, Self> { [Self::Opencomposite, Self::Xrizer, Self::Vapor].iter() } + + pub fn get_missing_deps(&self) -> Vec { + match self { + OvrCompatibilityModuleType::Xrizer => get_missing_xrizer_deps(), + OvrCompatibilityModuleType::Opencomposite | OvrCompatibilityModuleType::Vapor => { + Vec::default() + } + } + } } impl FromStr for OvrCompatibilityModuleType { @@ -737,7 +747,7 @@ impl Profile { if self.features.mercury_enabled { missing_deps.extend(get_missing_mercury_deps()); } - // no listed deps for opencomp + missing_deps.extend(self.ovr_comp.mod_type.get_missing_deps()); } missing_deps.sort_unstable(); missing_deps.dedup(); // dedup only works if sorted, hence the above From 27d37198c7876cb4d91d305414200c61e5677ac9 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sat, 10 May 2025 10:35:19 +0200 Subject: [PATCH 23/33] fix: refactor and optimize missing dependency filtering --- src/depcheck/basalt_deps.rs | 8 ++------ src/depcheck/libsurvive_deps.rs | 8 ++------ src/depcheck/mercury_deps.rs | 10 ++++------ src/depcheck/mod.rs | 18 ++++++++++++++++++ src/depcheck/monado_deps.rs | 8 ++------ src/depcheck/openhmd_deps.rs | 8 ++------ src/depcheck/wivrn_deps.rs | 8 ++------ src/depcheck/xrizer_deps.rs | 8 ++------ 8 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/depcheck/basalt_deps.rs b/src/depcheck/basalt_deps.rs index 2a05826..00a29b6 100644 --- a/src/depcheck/basalt_deps.rs +++ b/src/depcheck/basalt_deps.rs @@ -1,7 +1,7 @@ use super::{ boost_deps::boost_deps, common::{dep_cmake, dep_eigen, dep_gpp, dep_libgl, dep_ninja, dep_opencv}, - DepType, Dependency, DependencyCheckResult, + DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; use crate::linux_distro::LinuxDistro; use std::collections::HashMap; @@ -181,9 +181,5 @@ pub fn check_basalt_deps() -> Vec { } pub fn get_missing_basalt_deps() -> Vec { - check_basalt_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_basalt_deps().filter_missing_deps() } diff --git a/src/depcheck/libsurvive_deps.rs b/src/depcheck/libsurvive_deps.rs index c9e8d9c..46eec55 100644 --- a/src/depcheck/libsurvive_deps.rs +++ b/src/depcheck/libsurvive_deps.rs @@ -1,6 +1,6 @@ use super::{ common::{dep_cmake, dep_eigen, dep_gcc, dep_git, dep_gpp, dep_ninja}, - Dependency, DependencyCheckResult, + DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; fn libsurvive_deps() -> Vec { @@ -19,9 +19,5 @@ pub fn check_libsurvive_deps() -> Vec { } pub fn get_missing_libsurvive_deps() -> Vec { - check_libsurvive_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_libsurvive_deps().filter_missing_deps() } diff --git a/src/depcheck/mercury_deps.rs b/src/depcheck/mercury_deps.rs index cad3c80..a7e59be 100644 --- a/src/depcheck/mercury_deps.rs +++ b/src/depcheck/mercury_deps.rs @@ -1,4 +1,6 @@ -use super::{common::dep_opencv, DepType, Dependency, DependencyCheckResult}; +use super::{ + common::dep_opencv, DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult, +}; use crate::linux_distro::LinuxDistro; use std::collections::HashMap; @@ -39,9 +41,5 @@ pub fn check_mercury_deps() -> Vec { } pub fn get_missing_mercury_deps() -> Vec { - check_mercury_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_mercury_deps().filter_missing_deps() } diff --git a/src/depcheck/mod.rs b/src/depcheck/mod.rs index e46b1e7..92154bb 100644 --- a/src/depcheck/mod.rs +++ b/src/depcheck/mod.rs @@ -109,6 +109,24 @@ impl Display for DependencyCheckResult { } } +pub trait DepcheckResultGetMissing { + fn filter_missing_deps(self) -> Vec; +} + +impl DepcheckResultGetMissing for Vec { + fn filter_missing_deps(self) -> Vec { + self.into_iter() + .filter_map(|res| { + if !res.found { + Some(res.dependency) + } else { + None + } + }) + .collect() + } +} + fn shared_obj_paths() -> Vec { vec![ "/lib".into(), diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index b4894da..e1cd9f9 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -4,7 +4,7 @@ use super::{ dep_libgl, dep_libudev, dep_libx11, dep_libxcb, dep_ninja, dep_openxr, dep_vulkan_headers, dep_vulkan_icd_loader, }, - DepType, Dependency, DependencyCheckResult, + DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; use crate::{depcheck::common::dep_libxrandr, linux_distro::LinuxDistro}; use std::collections::HashMap; @@ -131,9 +131,5 @@ pub fn check_monado_deps() -> Vec { } pub fn get_missing_monado_deps() -> Vec { - check_monado_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_monado_deps().filter_missing_deps() } diff --git a/src/depcheck/openhmd_deps.rs b/src/depcheck/openhmd_deps.rs index 819324f..d31d013 100644 --- a/src/depcheck/openhmd_deps.rs +++ b/src/depcheck/openhmd_deps.rs @@ -1,6 +1,6 @@ use super::{ common::{dep_gcc, dep_git, dep_gpp, dep_ninja}, - Dependency, DependencyCheckResult, + DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; use crate::linux_distro::LinuxDistro; use std::collections::HashMap; @@ -31,9 +31,5 @@ pub fn check_openhmd_deps() -> Vec { } pub fn get_missing_openhmd_deps() -> Vec { - check_openhmd_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_openhmd_deps().filter_missing_deps() } diff --git a/src/depcheck/wivrn_deps.rs b/src/depcheck/wivrn_deps.rs index acf9a35..9126272 100644 --- a/src/depcheck/wivrn_deps.rs +++ b/src/depcheck/wivrn_deps.rs @@ -4,7 +4,7 @@ use super::{ dep_libudev, dep_libx11, dep_libxcb, dep_ninja, dep_openxr, dep_vulkan_headers, dep_vulkan_icd_loader, }, - DepType, Dependency, DependencyCheckResult, + DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; use crate::{ depcheck::common::{dep_libgl, dep_libxrandr}, @@ -270,9 +270,5 @@ pub fn check_wivrn_deps() -> Vec { } pub fn get_missing_wivrn_deps() -> Vec { - check_wivrn_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_wivrn_deps().filter_missing_deps() } diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs index ec48b4b..83134c1 100644 --- a/src/depcheck/xrizer_deps.rs +++ b/src/depcheck/xrizer_deps.rs @@ -1,4 +1,4 @@ -use super::{DepType, Dependency, DependencyCheckResult}; +use super::{DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult}; use crate::linux_distro::LinuxDistro; use std::collections::HashMap; @@ -49,9 +49,5 @@ pub fn check_xrizer_deps() -> Vec { } pub fn get_missing_xrizer_deps() -> Vec { - check_xrizer_deps() - .iter() - .filter(|res| !res.found) - .map(|res| res.dependency.clone()) - .collect() + check_xrizer_deps().filter_missing_deps() } From fc4a2d3993d4cfd363537114b491b5b3da937e3a Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sat, 10 May 2025 10:39:53 +0200 Subject: [PATCH 24/33] fix: deduplicate glslc dependency --- src/depcheck/common.rs | 16 ++++++++++++++++ src/depcheck/monado_deps.rs | 19 +++++-------------- src/depcheck/xrizer_deps.rs | 16 ++-------------- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/depcheck/common.rs b/src/depcheck/common.rs index dcae582..901d0ff 100644 --- a/src/depcheck/common.rs +++ b/src/depcheck/common.rs @@ -319,3 +319,19 @@ pub fn dep_getcap_setcap() -> Dependency { ]), } } + +pub fn dep_glslc() -> Dependency { + Dependency { + name: "glslc".into(), + dep_type: DepType::Executable, + filename: "glslc".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "shaderc".into()), + (LinuxDistro::Debian, "glslc".into()), + (LinuxDistro::Fedora, "glslc".into()), + (LinuxDistro::Alpine, "shaderc".into()), + (LinuxDistro::Gentoo, "media-libs/shaderc".into()), + (LinuxDistro::Suse, "shaderc".into()), + ]), + } +} diff --git a/src/depcheck/monado_deps.rs b/src/depcheck/monado_deps.rs index e1cd9f9..f9e1b9b 100644 --- a/src/depcheck/monado_deps.rs +++ b/src/depcheck/monado_deps.rs @@ -6,7 +6,10 @@ use super::{ }, DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult, }; -use crate::{depcheck::common::dep_libxrandr, linux_distro::LinuxDistro}; +use crate::{ + depcheck::common::{dep_glslc, dep_libxrandr}, + linux_distro::LinuxDistro, +}; use std::collections::HashMap; fn monado_deps() -> Vec { @@ -60,19 +63,7 @@ fn monado_deps() -> Vec { dep_ninja(), dep_gcc(), dep_gpp(), - Dependency { - name: "glslc".into(), - dep_type: DepType::Executable, - filename: "glslc".into(), - packages: HashMap::from([ - (LinuxDistro::Arch, "shaderc".into()), - (LinuxDistro::Debian, "glslc".into()), - (LinuxDistro::Fedora, "glslc".into()), - (LinuxDistro::Alpine, "shaderc".into()), - (LinuxDistro::Gentoo, "media-libs/shaderc".into()), - (LinuxDistro::Suse, "shaderc".into()), - ]), - }, + dep_glslc(), dep_glslang_validator(), Dependency { name: "sdl2".into(), diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs index 83134c1..a43bd20 100644 --- a/src/depcheck/xrizer_deps.rs +++ b/src/depcheck/xrizer_deps.rs @@ -1,22 +1,10 @@ use super::{DepType, DepcheckResultGetMissing, Dependency, DependencyCheckResult}; -use crate::linux_distro::LinuxDistro; +use crate::{depcheck::common::dep_glslc, linux_distro::LinuxDistro}; use std::collections::HashMap; fn xrizer_deps() -> Vec { vec![ - Dependency { - name: "glslc".into(), - dep_type: DepType::Executable, - filename: "glslc".into(), - packages: HashMap::from([ - (LinuxDistro::Arch, "shaderc".into()), - (LinuxDistro::Debian, "glslc".into()), - (LinuxDistro::Fedora, "glslc".into()), - (LinuxDistro::Alpine, "glslc".into()), - (LinuxDistro::Gentoo, "dev-util/glslang".into()), - (LinuxDistro::Suse, "shaderc".into()), - ]), - }, + dep_glslc(), Dependency { name: "libxcb-glx".into(), dep_type: DepType::Include, From 93ea2501b441f6f2a1ce42579d36a52784ffee6a Mon Sep 17 00:00:00 2001 From: Sapphire Date: Sat, 10 May 2025 09:27:17 -0500 Subject: [PATCH 25/33] fix: add gentoo library paths for libclang to search paths --- src/depcheck/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/depcheck/mod.rs b/src/depcheck/mod.rs index 92154bb..6e484d2 100644 --- a/src/depcheck/mod.rs +++ b/src/depcheck/mod.rs @@ -136,6 +136,13 @@ fn shared_obj_paths() -> Vec { "/usr/local/lib64".into(), "/usr/lib/x86_64-linux-gnu".into(), "/usr/lib/aarch64-linux-gnu".into(), + // Gentoo puts libclang in /usr/lib/llvm/[llvm major version]/lib64. + "/usr/lib/llvm/15/lib64".into(), + "/usr/lib/llvm/16/lib64".into(), + "/usr/lib/llvm/17/lib64".into(), + "/usr/lib/llvm/18/lib64".into(), + "/usr/lib/llvm/19/lib64".into(), + "/usr/lib/llvm/20/lib64".into(), "/lib/x86_64-linux-gnu".into(), "/lib/aarch64-linux-gnu".into(), "/app/lib".into(), From b174fab6bf85eeb14af2ad3f0e7427f1b9fb4b4c Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Wed, 14 May 2025 07:25:26 +0200 Subject: [PATCH 26/33] fix: add wayland-dev to xrizer dependencies --- src/depcheck/mod.rs | 2 ++ src/depcheck/xrizer_deps.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/depcheck/mod.rs b/src/depcheck/mod.rs index 6e484d2..3364490 100644 --- a/src/depcheck/mod.rs +++ b/src/depcheck/mod.rs @@ -166,6 +166,8 @@ fn include_paths() -> Vec { "/usr/include/ffmpeg/libpostproc".into(), "/usr/include/ffmpeg/libswresample".into(), "/usr/include/ffmpeg/libswscale".into(), + // opensuse puts wayland-client.h here + "/usr/include/wayland".into(), ] } diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs index a43bd20..b433357 100644 --- a/src/depcheck/xrizer_deps.rs +++ b/src/depcheck/xrizer_deps.rs @@ -29,6 +29,18 @@ fn xrizer_deps() -> Vec { (LinuxDistro::Suse, "clang19-devel".into()), ]), }, + Dependency { + name: "wayland-dev".into(), + dep_type: DepType::Include, + filename: "wayland-client.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "wayland".into()), + (LinuxDistro::Debian, "libwayland-dev".into()), + (LinuxDistro::Fedora, "wayland-devel".into()), + (LinuxDistro::Gentoo, "dev-libs/wayland".into()), + (LinuxDistro::Suse, "wayland-devel".into()), + ]), + }, ] } From d42de840a2d1f2bb973278c45a873db75b773e25 Mon Sep 17 00:00:00 2001 From: Sapphire Date: Sun, 18 May 2025 15:35:48 -0500 Subject: [PATCH 27/33] fix: add more libclang library paths --- src/depcheck/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/depcheck/mod.rs b/src/depcheck/mod.rs index 3364490..f2565eb 100644 --- a/src/depcheck/mod.rs +++ b/src/depcheck/mod.rs @@ -136,6 +136,17 @@ fn shared_obj_paths() -> Vec { "/usr/local/lib64".into(), "/usr/lib/x86_64-linux-gnu".into(), "/usr/lib/aarch64-linux-gnu".into(), + // Debian puts libclang in /usr/lib/llvm-[llvm major version]/lib. + "/usr/lib/llvm-15/lib".into(), + "/usr/lib/llvm-16/lib".into(), + "/usr/lib/llvm-19/lib".into(), + // Fedora puts libclang in /usr/lib64/llvm[llvm major version]/lib as well as /usr/lib64. + "/usr/lib64/llvm15/lib".into(), + "/usr/lib64/llvm16/lib".into(), + "/usr/lib64/llvm17/lib".into(), + "/usr/lib64/llvm18/lib".into(), + "/usr/lib64/llvm19/lib".into(), + "/usr/lib64/llvm20/lib".into(), // Gentoo puts libclang in /usr/lib/llvm/[llvm major version]/lib64. "/usr/lib/llvm/15/lib64".into(), "/usr/lib/llvm/16/lib64".into(), From eed85abb2a3c14a78c386b7df4e20af3e806c865 Mon Sep 17 00:00:00 2001 From: Sapphire Date: Wed, 4 Jun 2025 02:45:31 -0500 Subject: [PATCH 28/33] fix: detect cachyos as arch --- src/linux_distro.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/linux_distro.rs b/src/linux_distro.rs index d08c71b..2fcd76a 100644 --- a/src/linux_distro.rs +++ b/src/linux_distro.rs @@ -115,6 +115,7 @@ impl LinuxDistro { || s.contains("steamos") || s.contains("steam os") || s.contains("endeavour") + || s.contains("cachyos") || s.contains("garuda") { return Some(Self::Arch); From 5139ed7ba339664527fce4a5b21d95e3cc51be71 Mon Sep 17 00:00:00 2001 From: Sapphire Date: Thu, 29 May 2025 01:17:20 -0500 Subject: [PATCH 29/33] fix(builders/basalt): limit to at most 6 build processes The Basalt build is quite memory hungry, causing people's systems to lock up and trigger the OOM killer during build. --- src/builders/build_basalt.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/builders/build_basalt.rs b/src/builders/build_basalt.rs index 0d8130f..b2a55bd 100644 --- a/src/builders/build_basalt.rs +++ b/src/builders/build_basalt.rs @@ -5,7 +5,10 @@ use crate::{ ui::job_worker::job::WorkerJob, util::file_utils::rm_rf, }; -use std::collections::{HashMap, VecDeque}; +use std::{ + collections::{HashMap, VecDeque}, + num::NonZero, +}; pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque { let mut jobs = VecDeque::::new(); @@ -40,10 +43,23 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque = HashMap::new(); for (k, v) in [ - ("CMAKE_BUILD_TYPE", "RelWithDebInfo"), - ("BUILD_TESTS", "off"), + // The basalt build uses a lot of RAM, so we have to limit the number of + // build processes to not starve the system of memory + // Limit to 6 build processes at most + ( + "CMAKE_BUILD_PARALLEL_LEVEL", + std::cmp::min( + 6, + std::thread::available_parallelism() + .map(NonZero::get) + .unwrap_or(2), + ) + .to_string(), + ), + ("CMAKE_BUILD_TYPE", "RelWithDebInfo".into()), + ("BUILD_TESTS", "off".into()), ] { - cmake_env.insert(k.to_string(), v.to_string()); + cmake_env.insert(k.to_string(), v); } cmake_env }), From 754395586e8c690343d9826b437dd0a98a34b154 Mon Sep 17 00:00:00 2001 From: micheal65536 Date: Thu, 12 Jun 2025 07:57:54 +0200 Subject: [PATCH 30/33] fix: properly build and install vapor Co-authored-by: Gabriele Musco --- src/builders/build_vapor.rs | 37 ++++++++++--------------------------- src/profile.rs | 5 ++--- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/builders/build_vapor.rs b/src/builders/build_vapor.rs index 10206fe..5a05932 100644 --- a/src/builders/build_vapor.rs +++ b/src/builders/build_vapor.rs @@ -2,12 +2,11 @@ use crate::{ build_tools::{cmake::Cmake, git::Git}, profile::Profile, termcolor::TermColor, - ui::job_worker::job::{FuncWorkerData, FuncWorkerOut, WorkerJob}, - util::file_utils::{copy_file, rm_rf}, + ui::job_worker::job::WorkerJob, + util::file_utils::rm_rf, }; use std::{ collections::{HashMap, VecDeque}, - fs::create_dir_all, path::Path, }; @@ -37,16 +36,22 @@ pub fn get_build_vapor_jobs(profile: &Profile, clean_build: bool) -> VecDeque = HashMap::new(); for (k, v) in [ - ("VAPOR_LOG_SILENT=ON", "ON"), + ("VAPOR_LOG_SILENT", "ON"), + ("USE_SYSTEM_OPENXR", "OFF"), ("CMAKE_BUILD_TYPE", "RelWithDebInfo"), ] { cmake_vars.insert(k.to_string(), v.to_string()); } + cmake_vars.insert( + "CMAKE_INSTALL_PREFIX".into(), + install_dir.to_string_lossy().to_string(), + ); cmake_vars }), source_dir: profile.ovr_comp.path.clone(), @@ -57,29 +62,7 @@ pub fn get_build_vapor_jobs(profile: &Profile, clean_build: bool) -> VecDeque PathBuf { match self.mod_type { - OvrCompatibilityModuleType::Opencomposite | OvrCompatibilityModuleType::Vapor => { - self.path.join("build") - } + OvrCompatibilityModuleType::Opencomposite => self.path.join("build"), + OvrCompatibilityModuleType::Vapor => self.path.join("build/install_pfx/lib/VapoR"), OvrCompatibilityModuleType::Xrizer => self.path.join("target/release"), } } From 1cad5c4d1bdd83cdc74bdbe6b4797aacdbed31e0 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sat, 14 Jun 2025 17:27:59 +0200 Subject: [PATCH 31/33] fix: add cargo as xrizer dependency fixes #218 --- src/depcheck/xrizer_deps.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs index b433357..9d3591f 100644 --- a/src/depcheck/xrizer_deps.rs +++ b/src/depcheck/xrizer_deps.rs @@ -5,6 +5,18 @@ use std::collections::HashMap; fn xrizer_deps() -> Vec { vec![ dep_glslc(), + Dependency { + name: "cargo".into(), + dep_type: DepType::Executable, + filename: "cargo".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "rust".into()), + (LinuxDistro::Debian, "cargo".into()), + (LinuxDistro::Fedora, "cargo".into()), + (LinuxDistro::Alpine, "cargo".into()), + (LinuxDistro::Suse, "cargo".into()), + ]) + }, Dependency { name: "libxcb-glx".into(), dep_type: DepType::Include, From bd0cc9e2b174033b3736eddf3253c858712c3083 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sat, 14 Jun 2025 17:28:39 +0200 Subject: [PATCH 32/33] chore: format --- src/depcheck/xrizer_deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/depcheck/xrizer_deps.rs b/src/depcheck/xrizer_deps.rs index 9d3591f..49d9354 100644 --- a/src/depcheck/xrizer_deps.rs +++ b/src/depcheck/xrizer_deps.rs @@ -15,7 +15,7 @@ fn xrizer_deps() -> Vec { (LinuxDistro::Fedora, "cargo".into()), (LinuxDistro::Alpine, "cargo".into()), (LinuxDistro::Suse, "cargo".into()), - ]) + ]), }, Dependency { name: "libxcb-glx".into(), From 8f3f9b8759eecca4768f4860cbf6dc878337fb82 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Sat, 14 Jun 2025 17:53:05 +0200 Subject: [PATCH 33/33] feat: add some messages related to setcap output to build window; add build completed message to build window --- src/ui/app.rs | 24 ++++++++++++++++++++++++ src/ui/build_window.rs | 16 ++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/ui/app.rs b/src/ui/app.rs index 4cc6520..6201648 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -43,6 +43,7 @@ use crate::{ steam_linux_runtime_injector::{ restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile, }, + termcolor::TermColor, util::file_utils::{ setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd, verify_cap_sys_nice_eip, }, @@ -653,6 +654,10 @@ impl AsyncComponent for App { if dep_pkexec().check() { self.setcap_confirm_dialog.present(Some(&self.app_win)); } else { + self.build_window + .sender() + .emit(BuildWindowMsg::UpdateContent(vec![TermColor::Red + .colorize("pkexec not found, cannot set capabilities\n")])); alert_w_widget( "pkexec not found", Some(&format!( @@ -734,6 +739,7 @@ impl AsyncComponent for App { } Msg::RunSetCap => { if !dep_pkexec().check() { + // there's a precheck ahead of this, this should likely never happen error!("pkexec not found, skipping setcap"); } else { let profile = self.get_selected_profile(); @@ -751,8 +757,26 @@ impl AsyncComponent for App { if let Err(e) = setcap_cap_sys_nice_eip(&profile).await { setcap_failed_dialog(); error!("failed running setcap: {e}"); + self.build_window + .sender() + .emit(BuildWindowMsg::UpdateContent(vec![ + TermColor::Red.colorize("Setting capabilities failed\n") + ])); } else if !verify_cap_sys_nice_eip(&profile).await { setcap_failed_dialog(); + error!("setcap succeeded but capabilities were reset"); + self.build_window + .sender() + .emit(BuildWindowMsg::UpdateContent(vec![TermColor::Red + .colorize( + "Setting capabilities succeeded, but capabilities have been reset\n", + )])); + } else { + self.build_window + .sender() + .emit(BuildWindowMsg::UpdateContent(vec![ + TermColor::Green.colorize("Capabilities set correctly\n") + ])); } } } diff --git a/src/ui/build_window.rs b/src/ui/build_window.rs index 7b0ac69..f6f8b21 100644 --- a/src/ui/build_window.rs +++ b/src/ui/build_window.rs @@ -1,3 +1,5 @@ +use crate::termcolor::TermColor; + use super::{term_widget::TermWidget, SENDER_IO_ERR_MSG}; use adw::prelude::*; use relm4::prelude::*; @@ -164,8 +166,18 @@ impl SimpleComponent for BuildWindow { label.remove_css_class("success"); label.remove_css_class("error"); match status { - BuildStatus::Done => label.add_css_class("success"), - BuildStatus::Error(_) => label.add_css_class("error"), + BuildStatus::Done => { + label.add_css_class("success"); + sender.input(BuildWindowMsg::UpdateContent(vec![ + TermColor::Blue.colorize("Build completed!\n") + ])); + } + BuildStatus::Error(_) => { + label.add_css_class("error"); + sender.input(BuildWindowMsg::UpdateContent(vec![ + TermColor::Blue.colorize("Build failed!\n") + ])); + } _ => {} } if status != BuildStatus::Building {