diff --git a/src/file_builders/active_runtime_json.rs b/src/file_builders/active_runtime_json.rs index da430ea..18f8917 100644 --- a/src/file_builders/active_runtime_json.rs +++ b/src/file_builders/active_runtime_json.rs @@ -23,14 +23,21 @@ pub struct ActiveRuntime { pub runtime: ActiveRuntimeInnerRuntime, } -fn get_active_runtime_json_path() -> String { +pub fn get_openxr_conf_dir() -> String { format!( - "{config}/openxr/1/active_runtime.json", + "{config}/openxr", config = get_xdg_config_dir() ) } -pub fn is_steam(active_runtime: ActiveRuntime) -> bool { +fn get_active_runtime_json_path() -> String { + format!( + "{config}/1/active_runtime.json", + config = get_openxr_conf_dir() + ) +} + +pub fn is_steam(active_runtime: &ActiveRuntime) -> bool { match active_runtime.runtime.valve_runtime_is_steamvr { Some(true) => true, _ => false, @@ -45,16 +52,16 @@ pub fn get_current_active_runtime() -> Option { get_active_runtime_from_path(&get_active_runtime_json_path()) } -fn dump_active_runtime_to_path(active_runtime: ActiveRuntime, path_s: String) { - set_file_radonly(&path_s, false); - let writer = get_writer(&path_s); - serde_json::to_writer_pretty(writer, &active_runtime) +fn dump_active_runtime_to_path(active_runtime: &ActiveRuntime, path_s: &String) { + set_file_radonly(path_s, false); + let writer = get_writer(path_s); + serde_json::to_writer_pretty(writer, active_runtime) .expect_dialog("Unable to save active runtime"); - set_file_radonly(&path_s, true); + set_file_radonly(path_s, true); } -pub fn dump_current_active_runtime(active_runtime: ActiveRuntime) { - dump_active_runtime_to_path(active_runtime, get_active_runtime_json_path()); +pub fn dump_current_active_runtime(active_runtime: &ActiveRuntime) { + dump_active_runtime_to_path(active_runtime, &get_active_runtime_json_path()); } fn build_steam_active_runtime() -> ActiveRuntime { @@ -72,10 +79,10 @@ fn build_steam_active_runtime() -> ActiveRuntime { } pub fn set_current_active_runtime_to_steam() { - dump_current_active_runtime(build_steam_active_runtime()) + dump_current_active_runtime(&build_steam_active_runtime()) } -fn build_profile_active_runtime(profile: Profile) -> ActiveRuntime { +pub fn build_profile_active_runtime(profile: &Profile) -> ActiveRuntime { ActiveRuntime { file_format_version: "1.0.0".into(), runtime: ActiveRuntimeInnerRuntime { @@ -93,7 +100,7 @@ fn build_profile_active_runtime(profile: Profile) -> ActiveRuntime { } } -pub fn set_current_active_runtime_to_profile(profile: Profile) { +pub fn set_current_active_runtime_to_profile(profile: &Profile) { let pfx = profile.clone().prefix; let mut ar = build_profile_active_runtime(profile); // hack: relativize libopenxr_monado.so path for system installs @@ -111,7 +118,7 @@ pub fn set_current_active_runtime_to_profile(profile: Profile) { rels = rel_chain.join("/") ); } - dump_current_active_runtime(ar); + dump_current_active_runtime(&ar); } #[cfg(test)] @@ -146,6 +153,6 @@ mod tests { name: Some("SteamVR".into()), }, }; - dump_active_runtime_to_path(ar, "./target/testout/active_runtime.json.steamvr".into()); + dump_active_runtime_to_path(&ar, &"./target/testout/active_runtime.json.steamvr".into()); } } diff --git a/src/file_builders/openvrpaths_vrpath.rs b/src/file_builders/openvrpaths_vrpath.rs index a791db5..2b9805f 100644 --- a/src/file_builders/openvrpaths_vrpath.rs +++ b/src/file_builders/openvrpaths_vrpath.rs @@ -17,14 +17,21 @@ pub struct OpenVrPaths { version: u32, } -fn get_openvrpaths_vrpath_path() -> String { +pub fn get_openvr_conf_dir() -> String { format!( - "{config}/openvr/openvrpaths.vrpath", + "{config}/openvr", config = get_xdg_config_dir() ) } -pub fn is_steam(ovr_paths: OpenVrPaths) -> bool { +fn get_openvrpaths_vrpath_path() -> String { + format!( + "{config}/openvrpaths.vrpath", + config = get_openvr_conf_dir() + ) +} + +pub fn is_steam(ovr_paths: &OpenVrPaths) -> bool { ovr_paths .runtime .iter() @@ -43,15 +50,15 @@ pub fn get_current_openvrpaths() -> Option { get_openvrpaths_from_path(&get_openvrpaths_vrpath_path()) } -fn dump_openvrpaths_to_path(ovr_paths: OpenVrPaths, path_s: String) { - set_file_radonly(&path_s, false); - let writer = get_writer(&path_s); - serde_json::to_writer_pretty(writer, &ovr_paths).expect_dialog("Unable to save openvrpaths"); - set_file_radonly(&path_s, true); +fn dump_openvrpaths_to_path(ovr_paths: &OpenVrPaths, path_s: &String) { + set_file_radonly(path_s, false); + let writer = get_writer(path_s); + serde_json::to_writer_pretty(writer, ovr_paths).expect_dialog("Unable to save openvrpaths"); + set_file_radonly(path_s, true); } -pub fn dump_current_openvrpaths(ovr_paths: OpenVrPaths) { - dump_openvrpaths_to_path(ovr_paths, get_openvrpaths_vrpath_path()) +pub fn dump_current_openvrpaths(ovr_paths: &OpenVrPaths) { + dump_openvrpaths_to_path(ovr_paths, &get_openvrpaths_vrpath_path()) } fn build_steam_openvrpaths() -> OpenVrPaths { @@ -70,10 +77,10 @@ fn build_steam_openvrpaths() -> OpenVrPaths { } pub fn set_current_openvrpaths_to_steam() { - dump_current_openvrpaths(build_steam_openvrpaths()) + dump_current_openvrpaths(&build_steam_openvrpaths()) } -fn build_profile_openvrpaths(profile: Profile) -> OpenVrPaths { +pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths { let datadir = get_xdg_data_dir(); OpenVrPaths { config: vec![format!("{data}/Steam/config", data = datadir)], @@ -88,8 +95,8 @@ fn build_profile_openvrpaths(profile: Profile) -> OpenVrPaths { } } -pub fn set_current_openvrpaths_to_profile(profile: Profile) { - dump_current_openvrpaths(build_profile_openvrpaths(profile)) +pub fn set_current_openvrpaths_to_profile(profile: &Profile) { + dump_current_openvrpaths(&build_profile_openvrpaths(profile)) } #[cfg(test)] @@ -119,6 +126,6 @@ mod tests { runtime: vec!["/home/user/.local/share/Steam/steamapps/common/SteamVR".into()], version: 1, }; - dump_openvrpaths_to_path(ovrp, "./target/testout/openvrpaths.vrpath".into()) + dump_openvrpaths_to_path(&ovrp, &"./target/testout/openvrpaths.vrpath".into()) } } diff --git a/src/file_utils.rs b/src/file_utils.rs index b94ea1b..427adbe 100644 --- a/src/file_utils.rs +++ b/src/file_utils.rs @@ -2,7 +2,7 @@ use crate::{constants::CMD_NAME, runner::Runner}; use expect_dialog::ExpectDialog; use std::{ env, - fs::{self, create_dir_all, File, OpenOptions}, + fs::{self, create_dir_all, remove_dir_all, File, OpenOptions}, io::{BufReader, BufWriter}, path::Path, }; @@ -78,6 +78,10 @@ pub fn get_xdg_cache_dir() -> String { } } +pub fn get_xdg_runtime_dir() -> String { + env::var("XDG_RUNTIME_DIR").expect_dialog("XDG_RUNTIME_DIR is not set") +} + pub fn get_config_dir() -> String { format!( "{config}/{name}", @@ -137,3 +141,10 @@ pub fn get_exec_prefix() -> String { .unwrap() .to_string() } + +pub fn rm_rf(path_s: &String) { + match remove_dir_all(path_s) { + Err(_) => println!("Failed to remove path {}", path_s), + Ok(_) => {} + } +} diff --git a/src/profile.rs b/src/profile.rs index a50c743..49ec118 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -173,27 +173,32 @@ impl Default for Profile { impl Profile { pub fn get_steam_launch_options(&self) -> String { - let mut opts = vec![]; - opts.push(format!( - "XR_RUNTIME_JSON={prefix}/share/openxr/1/openxr_{runtime}.json", - prefix = match self.prefix.as_str() { - SYSTEM_PREFIX => BWRAP_SYSTEM_PREFIX, - other => other, - }, - runtime = match self.xrservice_type { - XRServiceType::Monado => "monado", - XRServiceType::Wivrn => "wivrn", - } - )); - opts.push(format!( - "PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/{xrservice}_comp_ipc", - xrservice = match self.xrservice_type { - XRServiceType::Monado => "monado", - XRServiceType::Wivrn => "wivrn", - } - )); - opts.push("%command%".into()); - opts.join(" ") + vec![ + format!( + "VR_OVERRIDE={opencomp}/build", + opencomp = self.opencomposite_path, + ), + format!( + "XR_RUNTIME_JSON={prefix}/share/openxr/1/openxr_{runtime}.json", + prefix = match self.prefix.as_str() { + SYSTEM_PREFIX => BWRAP_SYSTEM_PREFIX, + other => other, + }, + runtime = match self.xrservice_type { + XRServiceType::Monado => "monado", + XRServiceType::Wivrn => "wivrn", + } + ), + format!( + "PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/{xrservice}_comp_ipc", + xrservice = match self.xrservice_type { + XRServiceType::Monado => "monado", + XRServiceType::Wivrn => "wivrn", + } + ), + "%command%".into(), + ] + .join(" ") } pub fn load_profile(path: &String) -> Self { diff --git a/src/ui/app.rs b/src/ui/app.rs index 62e7290..1d6f2eb 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -18,6 +18,8 @@ use crate::dependencies::mercury_deps::get_missing_mercury_deps; use crate::dependencies::monado_deps::get_missing_monado_deps; use crate::dependencies::pkexec_dep::pkexec_dep; use crate::dependencies::wivrn_deps::get_missing_wivrn_deps; +use crate::file_builders::active_runtime_json::{set_current_active_runtime_to_profile, set_current_active_runtime_to_steam}; +use crate::file_builders::openvrpaths_vrpath::{set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam}; use crate::file_utils::setcap_cap_sys_nice_eip; use crate::log_parser::MonadoLog; use crate::profile::{Profile, XRServiceType}; @@ -94,7 +96,6 @@ pub enum Msg { OpenLibsurviveSetup, Quit, ProcessDevicesLog(Vec), - InhibitSession(bool), } impl App { @@ -134,6 +135,8 @@ impl App { pub fn start_xrservice(&mut self) { self.set_inhibit_session(true); let prof = self.get_selected_profile(); + set_current_active_runtime_to_profile(&prof); + set_current_openvrpaths_to_profile(&prof); self.devices_processed = match prof.xrservice_type { XRServiceType::Monado => false, XRServiceType::Wivrn => true, // no device from log in wivrn @@ -156,6 +159,20 @@ impl App { }; } + pub fn shutdown_xrservice(&mut self) { + if self.xrservice_runner.is_some() { + if self.xrservice_runner.as_mut().unwrap().status() == RunnerStatus::Running { + self.xrservice_runner.as_mut().unwrap().terminate(); + } + } + set_current_active_runtime_to_steam(); + set_current_openvrpaths_to_steam(); + self.set_inhibit_session(false); + self.main_view + .sender() + .emit(MainViewMsg::XRServiceActiveChanged(false, None)); + } + pub fn profiles_list(config: &Config) -> Vec { let mut profiles = vec![ valve_index_profile(), @@ -200,17 +217,18 @@ impl SimpleComponent for App { }, model.debug_view.widget(), } - } + }, } } fn shutdown(&mut self, widgets: &mut Self::Widgets, output: relm4::Sender) { - match &mut self.xrservice_runner { - None => {} - Some(runner) => { - runner.terminate(); + if self.xrservice_runner.is_some() { + if self.xrservice_runner.as_mut().unwrap().status() == RunnerStatus::Running { + self.xrservice_runner.as_mut().unwrap().terminate(); } } + set_current_active_runtime_to_steam(); + set_current_openvrpaths_to_steam(); } fn update(&mut self, message: Self::Input, sender: ComponentSender) { @@ -320,18 +338,13 @@ impl SimpleComponent for App { } Some(runner) => match runner.status() { RunnerStatus::Running => { - sender.input(Msg::InhibitSession(false)); - runner.terminate(); - self.main_view - .sender() - .emit(MainViewMsg::XRServiceActiveChanged(false, None)); + self.shutdown_xrservice(); } RunnerStatus::Stopped(_) => { self.start_xrservice(); } }, }, - Msg::InhibitSession(state) => self.set_inhibit_session(state), Msg::BuildProfile => { let profile = self.get_selected_profile(); let mut missing_deps = vec![]; diff --git a/src/ui/main_view.rs b/src/ui/main_view.rs index 6c43ed2..2038e6e 100644 --- a/src/ui/main_view.rs +++ b/src/ui/main_view.rs @@ -1,9 +1,6 @@ use super::devices_box::{DevicesBox, DevicesBoxMsg}; use super::install_wivrn_box::{InstallWivrnBox, InstallWivrnBoxInit, InstallWivrnBoxMsg}; use super::profile_editor::{ProfileEditor, ProfileEditorMsg, ProfileEditorOutMsg}; -use super::runtime_switcher_box::{ - RuntimeSwitcherBox, RuntimeSwitcherBoxInit, RuntimeSwitcherBoxMsg, -}; use super::steam_launch_options_box::{SteamLaunchOptionsBox, SteamLaunchOptionsBoxMsg}; use crate::config::Config; use crate::constants::APP_NAME; @@ -32,8 +29,6 @@ pub struct MainView { #[tracker::do_not_track] steam_launch_options_box: Controller, #[tracker::do_not_track] - runtime_switcher_box: Controller, - #[tracker::do_not_track] devices_box: Controller, #[tracker::do_not_track] profile_editor: Controller, @@ -147,7 +142,6 @@ impl SimpleComponent for MainView { }, }, model.devices_box.widget(), - model.runtime_switcher_box.widget(), model.steam_launch_options_box.widget(), model.install_wivrn_box.widget(), } @@ -250,9 +244,6 @@ impl SimpleComponent for MainView { self.install_wivrn_box .sender() .emit(InstallWivrnBoxMsg::UpdateSelectedProfile(prof.clone())); - self.runtime_switcher_box - .sender() - .emit(RuntimeSwitcherBoxMsg::UpdateSelectedProfile(prof.clone())); } Self::Input::UpdateProfiles(profiles, config) => { self.set_profiles(profiles); @@ -376,11 +367,6 @@ impl SimpleComponent for MainView { root_win: init.root_win.clone(), }) .detach(), - runtime_switcher_box: RuntimeSwitcherBox::builder() - .launch(RuntimeSwitcherBoxInit { - selected_profile: init.selected_profile.clone(), - }) - .detach(), profile_editor: ProfileEditor::builder() .launch(ProfileEditorInit { root_win: init.root_win.clone(), diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 7b7a7a3..8f3bb0b 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -6,7 +6,6 @@ pub mod build_window; pub mod libsurvive_setup_window; pub mod install_wivrn_box; pub mod steam_launch_options_box; -pub mod runtime_switcher_box; pub mod profile_editor; pub mod factories; pub mod wivrn_conf_editor; diff --git a/src/ui/runtime_switcher_box.rs b/src/ui/runtime_switcher_box.rs deleted file mode 100644 index 1eb2789..0000000 --- a/src/ui/runtime_switcher_box.rs +++ /dev/null @@ -1,109 +0,0 @@ -use relm4::prelude::*; -use gtk::prelude::*; -use crate::{constants::APP_NAME, file_builders::{active_runtime_json::{get_current_active_runtime, self, set_current_active_runtime_to_profile, set_current_active_runtime_to_steam}, openvrpaths_vrpath::{set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam}}, profile::Profile}; - -pub struct RuntimeSwitcherBox { - selected_profile: Profile, -} - -#[derive(Debug)] -pub enum RuntimeSwitcherBoxMsg { - UpdateSelectedProfile(Profile), - SetXRServiceRuntime(bool), -} - -pub struct RuntimeSwitcherBoxInit { - pub selected_profile: Profile, -} - -#[relm4::component(pub)] -impl SimpleComponent for RuntimeSwitcherBox { - type Init = RuntimeSwitcherBoxInit; - type Input = RuntimeSwitcherBoxMsg; - type Output = (); - - view! { - gtk::Box { - set_orientation: gtk::Orientation::Vertical, - set_hexpand: true, - set_spacing: 12, - gtk::Separator { - set_orientation: gtk::Orientation::Horizontal, - set_hexpand: true, - }, - gtk::Label { - add_css_class: "heading", - set_hexpand: true, - set_xalign: 0.0, - set_margin_start: 12, - set_margin_end: 12, - set_label: "OpenXR/OpenVR Runtime", - set_wrap: true, - set_wrap_mode: gtk::pango::WrapMode::Word, - }, - gtk::Box { - set_orientation: gtk::Orientation::Horizontal, - set_hexpand: true, - set_halign: gtk::Align::Start, - set_margin_start: 12, - set_margin_end: 12, - set_spacing: 12, - gtk::Label { - set_label: "Steam", - }, - #[name(runtime_switch)] - gtk::Switch { - }, - gtk::Label { - set_label: APP_NAME, - }, - }, - } - } - - fn update(&mut self, message: Self::Input, sender: ComponentSender) { - match message { - Self::Input::UpdateSelectedProfile(prof) => { - self.selected_profile = prof; - } - Self::Input::SetXRServiceRuntime(is_rex) => { - if is_rex { - set_current_active_runtime_to_profile(self.selected_profile.clone()); - set_current_openvrpaths_to_profile(self.selected_profile.clone()); - } else { - set_current_active_runtime_to_steam(); - set_current_openvrpaths_to_steam(); - } - } - } - } - - fn init( - init: Self::Init, - root: &Self::Root, - sender: ComponentSender, - ) -> ComponentParts { - let model = Self { - selected_profile: init.selected_profile, - }; - - let widgets = view_output!(); - - { - match get_current_active_runtime() { - None => {} - Some(runtime) => { - widgets - .runtime_switch - .set_active(!active_runtime_json::is_steam(runtime)); - } - } - widgets.runtime_switch.connect_state_set(move |_, state| { - sender.input(Self::Input::SetXRServiceRuntime(state)); - gtk::Inhibit(false) - }); - } - - ComponentParts { model, widgets } - } -} diff --git a/src/ui/steam_launch_options_box.rs b/src/ui/steam_launch_options_box.rs index a176db0..2890c72 100644 --- a/src/ui/steam_launch_options_box.rs +++ b/src/ui/steam_launch_options_box.rs @@ -64,22 +64,24 @@ impl SimpleComponent for SteamLaunchOptionsBox { set_margin_end: 12, set_orientation: gtk::Orientation::Horizontal, set_spacing: 6, - gtk::TextView { + gtk::ScrolledWindow { add_css_class: "card", - set_hexpand: true, - set_vexpand: false, - set_monospace: true, - set_editable: false, - set_wrap_mode: gtk::WrapMode::Word, - set_left_margin: 6, - set_right_margin: 6, - set_top_margin: 6, - set_bottom_margin: 6, - set_size_request: (-1, 150), - #[wrap(Some)] - set_buffer: cmdbuf = >k::TextBuffer { - #[track = "model.changed(Self::launch_options())"] - set_text: model.launch_options.as_str(), + set_vscrollbar_policy: gtk::PolicyType::Never, + set_overflow: gtk::Overflow::Hidden, + gtk::TextView { + set_hexpand: true, + set_vexpand: false, + set_monospace: true, + set_editable: false, + set_left_margin: 6, + set_right_margin: 6, + set_top_margin: 6, + set_bottom_margin: 18, + #[wrap(Some)] + set_buffer: cmdbuf = >k::TextBuffer { + #[track = "model.changed(Self::launch_options())"] + set_text: model.launch_options.as_str(), + } } }, gtk::Button {