mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-08-03 14:49:04 +00:00
Merge branch 'flatpak-packaging' into 'main'
Draft: feat: flatpak packaging See merge request gabmus/envision!90
This commit is contained in:
commit
c99c0eacb3
22 changed files with 273 additions and 72 deletions
96
dist/flatpak/org.gabmus.envision.json
vendored
Normal file
96
dist/flatpak/org.gabmus.envision.json
vendored
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"id": "org.gabmus.envision",
|
||||||
|
"branch": "47",
|
||||||
|
"runtime": "org.gnome.Sdk",
|
||||||
|
"runtime-version": "47",
|
||||||
|
"sdk": "org.gnome.Sdk",
|
||||||
|
"sdk-extensions": [
|
||||||
|
"org.freedesktop.Sdk.Extension.rust-stable",
|
||||||
|
"org.freedesktop.Sdk.Extension.llvm19"
|
||||||
|
],
|
||||||
|
"command": "envision",
|
||||||
|
"build-options": {
|
||||||
|
"append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm19/bin",
|
||||||
|
"env": {
|
||||||
|
"CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER": "clang",
|
||||||
|
"CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold",
|
||||||
|
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER": "clang",
|
||||||
|
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold"
|
||||||
|
},
|
||||||
|
"build-args": [
|
||||||
|
"--share=network"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"cleanup": [
|
||||||
|
"/share/doc",
|
||||||
|
"/share/man"
|
||||||
|
],
|
||||||
|
"finish-args": [
|
||||||
|
"--share=ipc",
|
||||||
|
"--share=network",
|
||||||
|
"--socket=wayland",
|
||||||
|
"--socket=fallback-x11",
|
||||||
|
"--socket=pulseaudio",
|
||||||
|
"--device=all",
|
||||||
|
"--filesystem=xdg-run/pipewire-0",
|
||||||
|
"--filesystem=xdg-run/monado_comp_ipc",
|
||||||
|
"--filesystem=~/.steam",
|
||||||
|
"--filesystem=~/.var/app/com.valvesoftware.Steam",
|
||||||
|
"--talk-name=org.freedesktop.Flatpak"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "OpenXR-SDK",
|
||||||
|
"buildsystem": "cmake",
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/KhronosGroup/OpenXR-SDK-Source.git",
|
||||||
|
"tag": "release-1.1.42"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vte",
|
||||||
|
"buildsystem": "meson",
|
||||||
|
"config-opts": [
|
||||||
|
"-Dgtk4=true",
|
||||||
|
"-Dgtk3=false"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "archive",
|
||||||
|
"url": "https://gitlab.gnome.org/GNOME/vte/-/archive/0.78.0/vte-0.78.0.tar.gz",
|
||||||
|
"sha256": "82e19d11780fed4b66400f000829ce5ca113efbbfb7975815f26ed93e4c05f2d"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "eigen",
|
||||||
|
"buildsystem": "cmake",
|
||||||
|
"builddir": true,
|
||||||
|
"build-options": {
|
||||||
|
"config-opts": [
|
||||||
|
"-DEIGEN_BUILD_CMAKE_PACKAGE=NO"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.com/libeigen/eigen.git",
|
||||||
|
"tag": "3.4.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Envision",
|
||||||
|
"buildsystem": "meson",
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "dir",
|
||||||
|
"path": "../../"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ use std::ffi::OsStr;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::{collections::HashMap, os::unix::process::ExitStatusExt};
|
use std::{collections::HashMap, os::unix::process::ExitStatusExt};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
use crate::is_flatpak::IS_FLATPAK;
|
||||||
|
|
||||||
pub struct AsyncProcessOut {
|
pub struct AsyncProcessOut {
|
||||||
pub exit_code: i32,
|
pub exit_code: i32,
|
||||||
|
@ -13,10 +14,22 @@ pub async fn async_process<S: AsRef<OsStr>, T: AsRef<OsStr>>(
|
||||||
cmd: S,
|
cmd: S,
|
||||||
args: Option<&[T]>,
|
args: Option<&[T]>,
|
||||||
env: Option<HashMap<String, String>>,
|
env: Option<HashMap<String, String>>,
|
||||||
|
host_spawn: bool,
|
||||||
) -> anyhow::Result<AsyncProcessOut> {
|
) -> anyhow::Result<AsyncProcessOut> {
|
||||||
let cmd = Command::new(cmd)
|
let mut command: Command;
|
||||||
.args(args.unwrap_or_default())
|
if *IS_FLATPAK && host_spawn {
|
||||||
.envs(env.unwrap_or_default())
|
command = Command::new("flatpak-spawn");
|
||||||
|
command.arg("--host");
|
||||||
|
for (key, value) in env.unwrap_or_default() {
|
||||||
|
command.arg(format!("--env={}={}", key, value));
|
||||||
|
}
|
||||||
|
command.arg(cmd).args(args.unwrap_or_default());
|
||||||
|
} else {
|
||||||
|
command = Command::new(cmd);
|
||||||
|
command.args(args.unwrap_or_default()).envs(env.unwrap_or_default());
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd = command
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl Cmake {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.push(self.source_dir.to_string_lossy().to_string());
|
args.push(self.source_dir.to_string_lossy().to_string());
|
||||||
WorkerJob::new_cmd(self.env.clone(), "cmake".into(), Some(args))
|
WorkerJob::new_cmd(self.env.clone(), "cmake".into(), Some(args), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_build_job(&self) -> WorkerJob {
|
pub fn get_build_job(&self) -> WorkerJob {
|
||||||
|
@ -37,6 +37,7 @@ impl Cmake {
|
||||||
"--build".into(),
|
"--build".into(),
|
||||||
self.build_dir.to_string_lossy().to_string(),
|
self.build_dir.to_string_lossy().to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ impl Cmake {
|
||||||
"--install".into(),
|
"--install".into(),
|
||||||
self.build_dir.to_string_lossy().to_string(),
|
self.build_dir.to_string_lossy().to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl Git {
|
||||||
fn cmd(&self, args: Vec<String>) -> WorkerJob {
|
fn cmd(&self, args: Vec<String>) -> WorkerJob {
|
||||||
let mut nargs = vec!["-C".into(), self.dir.to_string_lossy().to_string()];
|
let mut nargs = vec!["-C".into(), self.dir.to_string_lossy().to_string()];
|
||||||
nargs.extend(args);
|
nargs.extend(args);
|
||||||
WorkerJob::new_cmd(None, "git".into(), Some(nargs))
|
WorkerJob::new_cmd(None, "git".into(), Some(nargs), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_repo(&self) -> String {
|
fn get_repo(&self) -> String {
|
||||||
|
@ -84,6 +84,7 @@ impl Git {
|
||||||
self.dir.to_string_lossy().to_string(),
|
self.dir.to_string_lossy().to_string(),
|
||||||
"--recurse-submodules".into(),
|
"--recurse-submodules".into(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
jobs.push_back(WorkerJob::new_cmd(
|
jobs.push_back(WorkerJob::new_cmd(
|
||||||
None,
|
None,
|
||||||
|
@ -100,6 +101,7 @@ pub fn get_build_basalt_jobs(profile: &Profile, clean_build: bool) -> VecDeque<W
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
jobs
|
jobs
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub fn get_build_mercury_jobs(profile: &Profile) -> VecDeque<WorkerJob> {
|
||||||
profile.prefix.to_string_lossy().to_string(),
|
profile.prefix.to_string_lossy().to_string(),
|
||||||
get_cache_dir().to_string_lossy().to_string(),
|
get_cache_dir().to_string_lossy().to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
jobs
|
jobs
|
||||||
|
|
|
@ -62,6 +62,7 @@ pub fn get_build_openhmd_jobs(profile: &Profile, clean_build: bool) -> VecDeque<
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// build job
|
// build job
|
||||||
|
@ -69,6 +70,7 @@ pub fn get_build_openhmd_jobs(profile: &Profile, clean_build: bool) -> VecDeque<
|
||||||
None,
|
None,
|
||||||
"ninja".into(),
|
"ninja".into(),
|
||||||
Some(vec!["-C".into(), build_dir.to_string_lossy().to_string()]),
|
Some(vec!["-C".into(), build_dir.to_string_lossy().to_string()]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
// install job
|
// install job
|
||||||
jobs.push_back(WorkerJob::new_cmd(
|
jobs.push_back(WorkerJob::new_cmd(
|
||||||
|
@ -79,6 +81,7 @@ pub fn get_build_openhmd_jobs(profile: &Profile, clean_build: bool) -> VecDeque<
|
||||||
build_dir.to_string_lossy().to_string(),
|
build_dir.to_string_lossy().to_string(),
|
||||||
"install".into(),
|
"install".into(),
|
||||||
]),
|
]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
jobs
|
jobs
|
||||||
|
|
|
@ -125,6 +125,8 @@ fn include_paths() -> Vec<String> {
|
||||||
vec![
|
vec![
|
||||||
"/usr/include".into(),
|
"/usr/include".into(),
|
||||||
"/usr/local/include".into(),
|
"/usr/local/include".into(),
|
||||||
|
// flatpak applications use /app
|
||||||
|
"/app/include".into(),
|
||||||
// fedora puts avcodec here
|
// fedora puts avcodec here
|
||||||
"/usr/include/ffmpeg".into(),
|
"/usr/include/ffmpeg".into(),
|
||||||
"/usr/include/x86_64-linux-gnu".into(),
|
"/usr/include/x86_64-linux-gnu".into(),
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
paths::{get_backup_dir, SYSTEM_PREFIX},
|
is_flatpak::IS_FLATPAK, paths::{get_backup_dir, get_home_dir, SYSTEM_PREFIX}, profile::Profile, util::file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly}, xdg::XDG
|
||||||
profile::Profile,
|
|
||||||
util::file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
|
|
||||||
xdg::XDG,
|
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -138,17 +135,28 @@ fn relativize_active_runtime_lib_path(ar: &ActiveRuntime, path: &Path) -> Active
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_current_active_runtime_to_profile(profile: &Profile) -> anyhow::Result<()> {
|
pub fn set_current_active_runtime_to_profile(profile: &Profile) -> anyhow::Result<()> {
|
||||||
let dest = get_active_runtime_json_path();
|
let mut dests = vec![
|
||||||
set_file_readonly(&dest, false)?;
|
get_active_runtime_json_path(),
|
||||||
|
get_home_dir().join(".var/app/com.valvesoftware.Steam/config/openxr/1/active_runtime.json"),
|
||||||
|
];
|
||||||
|
if *IS_FLATPAK {
|
||||||
|
dests.push(get_home_dir().join(".config/openxr/1/active_runtime.json"));
|
||||||
|
}
|
||||||
backup_steam_active_runtime();
|
backup_steam_active_runtime();
|
||||||
let pfx = profile.clone().prefix;
|
let pfx: PathBuf = profile.clone().prefix;
|
||||||
|
for dest in dests {
|
||||||
|
if !dest.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let mut ar = build_profile_active_runtime(profile)?;
|
let mut ar = build_profile_active_runtime(profile)?;
|
||||||
// hack: relativize libopenxr_monado.so path for system installs
|
// hack: relativize libopenxr_monado.so path for system installs
|
||||||
if pfx == PathBuf::from(SYSTEM_PREFIX) {
|
if pfx == PathBuf::from(SYSTEM_PREFIX) {
|
||||||
ar = relativize_active_runtime_lib_path(&ar, &dest);
|
ar = relativize_active_runtime_lib_path(&ar, &dest);
|
||||||
}
|
}
|
||||||
dump_current_active_runtime(&ar)?;
|
set_file_readonly(&dest, false)?;
|
||||||
|
dump_active_runtime_to_path(&ar, &dest)?;
|
||||||
set_file_readonly(&dest, true)?;
|
set_file_readonly(&dest, true)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
paths::get_backup_dir,
|
is_flatpak::IS_FLATPAK, paths::{get_home_dir, get_backup_dir}, profile::Profile, util::file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly}, xdg::XDG
|
||||||
profile::Profile,
|
|
||||||
util::file_utils::{copy_file, deserialize_file, get_writer, set_file_readonly},
|
|
||||||
xdg::XDG,
|
|
||||||
};
|
};
|
||||||
use serde::{ser::Error, Deserialize, Serialize};
|
use serde::{ser::Error, Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -23,9 +20,19 @@ pub fn get_openvr_conf_dir() -> PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_openvrpaths_vrpath_path() -> PathBuf {
|
fn get_openvrpaths_vrpath_path() -> PathBuf {
|
||||||
|
if *IS_FLATPAK {
|
||||||
|
return get_home_dir().join(".config/openvr/openvrpaths.vrpath")
|
||||||
|
}
|
||||||
get_openvr_conf_dir().join("openvrpaths.vrpath")
|
get_openvr_conf_dir().join("openvrpaths.vrpath")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_openvrpaths_vrpaths() -> Vec<PathBuf> {
|
||||||
|
vec![
|
||||||
|
get_openvrpaths_vrpath_path(),
|
||||||
|
get_home_dir().join(".var/app/com.valvesoftware.Steam/config/openvr/openvrpaths.vrpath"),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_steam(ovr_paths: &OpenVrPaths) -> bool {
|
pub fn is_steam(ovr_paths: &OpenVrPaths) -> bool {
|
||||||
ovr_paths.runtime.iter().any(|rt| {
|
ovr_paths.runtime.iter().any(|rt| {
|
||||||
rt.to_string_lossy()
|
rt.to_string_lossy()
|
||||||
|
@ -104,11 +111,15 @@ pub fn build_profile_openvrpaths(profile: &Profile) -> OpenVrPaths {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<()> {
|
pub fn set_current_openvrpaths_to_profile(profile: &Profile) -> anyhow::Result<()> {
|
||||||
let dest = get_openvrpaths_vrpath_path();
|
|
||||||
set_file_readonly(&dest, false)?;
|
|
||||||
backup_steam_openvrpaths();
|
backup_steam_openvrpaths();
|
||||||
dump_current_openvrpaths(&build_profile_openvrpaths(profile))?;
|
for dest in get_openvrpaths_vrpaths() {
|
||||||
|
if !dest.is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
set_file_readonly(&dest, false)?;
|
||||||
|
dump_openvrpaths_to_path(&build_profile_openvrpaths(profile), &dest)?;
|
||||||
set_file_readonly(&dest, true)?;
|
set_file_readonly(&dest, true)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
src/is_flatpak.rs
Normal file
6
src/is_flatpak.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref IS_FLATPAK: bool = Path::new("/.flatpak-info").is_file();
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ pub mod env_var_descriptions;
|
||||||
pub mod file_builders;
|
pub mod file_builders;
|
||||||
pub mod gpu_profile;
|
pub mod gpu_profile;
|
||||||
pub mod is_appimage;
|
pub mod is_appimage;
|
||||||
|
pub mod is_flatpak;
|
||||||
pub mod linux_distro;
|
pub mod linux_distro;
|
||||||
pub mod log_parser;
|
pub mod log_parser;
|
||||||
pub mod openxr_prober;
|
pub mod openxr_prober;
|
||||||
|
|
|
@ -20,34 +20,21 @@ use crate::{
|
||||||
build_mercury::get_build_mercury_jobs, build_monado::get_build_monado_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_opencomposite::get_build_opencomposite_jobs, build_openhmd::get_build_openhmd_jobs,
|
||||||
build_wivrn::get_build_wivrn_jobs,
|
build_wivrn::get_build_wivrn_jobs,
|
||||||
},
|
}, config::Config, constants::APP_NAME, depcheck::{
|
||||||
config::Config,
|
|
||||||
constants::APP_NAME,
|
|
||||||
depcheck::{
|
|
||||||
basalt_deps::get_missing_basalt_deps, common::dep_pkexec,
|
basalt_deps::get_missing_basalt_deps, common::dep_pkexec,
|
||||||
libsurvive_deps::get_missing_libsurvive_deps, mercury_deps::get_missing_mercury_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,
|
monado_deps::get_missing_monado_deps, openhmd_deps::get_missing_openhmd_deps,
|
||||||
wivrn_deps::get_missing_wivrn_deps,
|
wivrn_deps::get_missing_wivrn_deps,
|
||||||
},
|
}, file_builders::{
|
||||||
file_builders::{
|
|
||||||
active_runtime_json::{
|
active_runtime_json::{
|
||||||
set_current_active_runtime_to_profile, set_current_active_runtime_to_steam,
|
set_current_active_runtime_to_profile, set_current_active_runtime_to_steam,
|
||||||
},
|
},
|
||||||
openvrpaths_vrpath::{
|
openvrpaths_vrpath::{
|
||||||
set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam,
|
set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam,
|
||||||
},
|
},
|
||||||
},
|
}, is_flatpak::IS_FLATPAK, linux_distro::LinuxDistro, openxr_prober::is_openxr_ready, paths::get_data_dir, profile::{Profile, XRServiceType}, stateless_action, steam_linux_runtime_injector::{
|
||||||
linux_distro::LinuxDistro,
|
|
||||||
openxr_prober::is_openxr_ready,
|
|
||||||
paths::get_data_dir,
|
|
||||||
profile::{Profile, XRServiceType},
|
|
||||||
stateless_action,
|
|
||||||
steam_linux_runtime_injector::{
|
|
||||||
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
|
restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile,
|
||||||
},
|
}, util::{cmd_utils::CommandUnsandbox, file_utils::{setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd}}, vulkaninfo::VulkanInfo, xr_devices::XRDevice
|
||||||
util::file_utils::{setcap_cap_sys_nice_eip, setcap_cap_sys_nice_eip_cmd},
|
|
||||||
vulkaninfo::VulkanInfo,
|
|
||||||
xr_devices::XRDevice,
|
|
||||||
};
|
};
|
||||||
use adw::{prelude::*, ResponseAppearance};
|
use adw::{prelude::*, ResponseAppearance};
|
||||||
use gtk::glib::{self, clone};
|
use gtk::glib::{self, clone};
|
||||||
|
@ -56,7 +43,7 @@ use relm4::{
|
||||||
new_action_group, new_stateful_action, new_stateless_action,
|
new_action_group, new_stateful_action, new_stateless_action,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use std::{collections::VecDeque, fs::remove_file, time::Duration};
|
use std::{collections::VecDeque, fs::remove_file, process::Command, time::Duration};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
application: adw::Application,
|
application: adw::Application,
|
||||||
|
@ -175,9 +162,16 @@ impl App {
|
||||||
};
|
};
|
||||||
self.debug_view.sender().emit(DebugViewMsg::ClearLog);
|
self.debug_view.sender().emit(DebugViewMsg::ClearLog);
|
||||||
self.xr_devices = vec![];
|
self.xr_devices = vec![];
|
||||||
|
if *IS_FLATPAK {
|
||||||
|
Command::new_unsandboxed("rm", None)
|
||||||
|
.arg(prof.xrservice_type.ipc_file_path().to_str().unwrap())
|
||||||
|
.output()
|
||||||
|
.expect("Failed to remove xrservice IPC file");
|
||||||
|
} else {
|
||||||
remove_file(prof.xrservice_type.ipc_file_path())
|
remove_file(prof.xrservice_type.ipc_file_path())
|
||||||
.is_err()
|
.is_err()
|
||||||
.then(|| println!("Failed to remove xrservice IPC file"));
|
.then(|| println!("Failed to remove xrservice IPC file"));
|
||||||
|
}
|
||||||
let worker = JobWorker::xrservice_worker_wrap_from_profile(
|
let worker = JobWorker::xrservice_worker_wrap_from_profile(
|
||||||
&prof,
|
&prof,
|
||||||
sender.input_sender(),
|
sender.input_sender(),
|
||||||
|
@ -222,6 +216,7 @@ impl App {
|
||||||
Some(prof.environment.clone()),
|
Some(prof.environment.clone()),
|
||||||
"sh".into(),
|
"sh".into(),
|
||||||
Some(vec!["-c".into(), autostart_cmd.clone()]),
|
Some(vec!["-c".into(), autostart_cmd.clone()]),
|
||||||
|
true
|
||||||
));
|
));
|
||||||
let autostart_worker = JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
let autostart_worker = JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
||||||
JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows),
|
JobWorkerOut::Log(rows) => Msg::OnServiceLog(rows),
|
||||||
|
@ -533,7 +528,7 @@ impl AsyncComponent for App {
|
||||||
.sender()
|
.sender()
|
||||||
.emit(BuildWindowMsg::UpdateBuildStatus(BuildStatus::Done));
|
.emit(BuildWindowMsg::UpdateBuildStatus(BuildStatus::Done));
|
||||||
let profile = self.get_selected_profile();
|
let profile = self.get_selected_profile();
|
||||||
if dep_pkexec().check() {
|
if dep_pkexec().check() || *IS_FLATPAK {
|
||||||
self.setcap_confirm_dialog.present(Some(&self.app_win));
|
self.setcap_confirm_dialog.present(Some(&self.app_win));
|
||||||
} else {
|
} else {
|
||||||
alert_w_widget(
|
alert_w_widget(
|
||||||
|
@ -606,11 +601,11 @@ impl AsyncComponent for App {
|
||||||
.emit(DebugViewMsg::UpdateSelectedProfile(prof.clone()));
|
.emit(DebugViewMsg::UpdateSelectedProfile(prof.clone()));
|
||||||
}
|
}
|
||||||
Msg::RunSetCap => {
|
Msg::RunSetCap => {
|
||||||
if !dep_pkexec().check() {
|
if dep_pkexec().check() || *IS_FLATPAK {
|
||||||
println!("pkexec not found, skipping setcap");
|
|
||||||
} else {
|
|
||||||
let profile = self.get_selected_profile();
|
let profile = self.get_selected_profile();
|
||||||
setcap_cap_sys_nice_eip(&profile).await;
|
setcap_cap_sys_nice_eip(&profile).await;
|
||||||
|
} else {
|
||||||
|
println!("pkexec not found, skipping setcap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Msg::ProfileSelected(prof) => {
|
Msg::ProfileSelected(prof) => {
|
||||||
|
@ -698,7 +693,7 @@ impl AsyncComponent for App {
|
||||||
let worker = JobWorker::new_with_timer(
|
let worker = JobWorker::new_with_timer(
|
||||||
Duration::from_millis(500),
|
Duration::from_millis(500),
|
||||||
WorkerJob::new_func(Box::new(move || {
|
WorkerJob::new_func(Box::new(move || {
|
||||||
let ready = is_openxr_ready();
|
let ready = !*IS_FLATPAK && is_openxr_ready();
|
||||||
FuncWorkerOut {
|
FuncWorkerOut {
|
||||||
success: ready,
|
success: ready,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -218,6 +218,7 @@ impl AsyncComponent for InstallWivrnBox {
|
||||||
"adb",
|
"adb",
|
||||||
Some(&["install", "-r", "-g", apk_path.to_string_lossy().to_string().as_str()]),
|
Some(&["install", "-r", "-g", apk_path.to_string_lossy().to_string().as_str()]),
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,19 +3,12 @@ use super::{
|
||||||
state::JobWorkerState,
|
state::JobWorkerState,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
profile::{LighthouseDriver, Profile},
|
profile::{LighthouseDriver, Profile}, ui::SENDER_IO_ERR_MSG, util::cmd_utils::CommandUnsandbox
|
||||||
ui::SENDER_IO_ERR_MSG,
|
|
||||||
};
|
};
|
||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
use relm4::{prelude::*, Worker};
|
use relm4::{prelude::*, Worker};
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque, io::{BufRead, BufReader}, mem, os::unix::process::ExitStatusExt, process::{Command, Stdio}, sync::{Arc, Mutex}, thread
|
||||||
io::{BufRead, BufReader},
|
|
||||||
mem,
|
|
||||||
os::unix::process::ExitStatusExt,
|
|
||||||
process::{Command, Stdio},
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! logger_thread {
|
macro_rules! logger_thread {
|
||||||
|
@ -92,9 +85,15 @@ impl Worker for InternalJobWorker {
|
||||||
match &mut job {
|
match &mut job {
|
||||||
WorkerJob::Cmd(data) => {
|
WorkerJob::Cmd(data) => {
|
||||||
let data = data.clone();
|
let data = data.clone();
|
||||||
if let Ok(mut cmd) = Command::new(data.command)
|
let mut cmd: Command;
|
||||||
|
if data.host_spawn {
|
||||||
|
cmd = Command::new_unsandboxed(&data.command, Some(data.environment))
|
||||||
|
} else {
|
||||||
|
cmd = Command::new(&data.command);
|
||||||
|
cmd.envs(data.environment);
|
||||||
|
}
|
||||||
|
if let Ok(mut cmd) = cmd
|
||||||
.args(data.args)
|
.args(data.args)
|
||||||
.envs(data.environment)
|
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
|
@ -221,9 +220,10 @@ impl InternalJobWorker {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let data = CmdWorkerData {
|
let data = CmdWorkerData {
|
||||||
environment: env,
|
environment: env.clone(),
|
||||||
command,
|
command: command.clone(),
|
||||||
args,
|
args: args.clone(),
|
||||||
|
host_spawn: true,
|
||||||
};
|
};
|
||||||
let mut jobs = VecDeque::new();
|
let mut jobs = VecDeque::new();
|
||||||
jobs.push_back(WorkerJob::Cmd(data));
|
jobs.push_back(WorkerJob::Cmd(data));
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub struct CmdWorkerData {
|
||||||
pub environment: HashMap<String, String>,
|
pub environment: HashMap<String, String>,
|
||||||
pub command: String,
|
pub command: String,
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
|
pub host_spawn: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -38,11 +39,13 @@ impl WorkerJob {
|
||||||
env: Option<HashMap<String, String>>,
|
env: Option<HashMap<String, String>>,
|
||||||
cmd: String,
|
cmd: String,
|
||||||
args: Option<Vec<String>>,
|
args: Option<Vec<String>>,
|
||||||
|
host_spawn: bool
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::Cmd(CmdWorkerData {
|
Self::Cmd(CmdWorkerData {
|
||||||
environment: env.unwrap_or_default(),
|
environment: env.unwrap_or_default(),
|
||||||
command: cmd,
|
command: cmd,
|
||||||
args: args.unwrap_or_default(),
|
args: args.unwrap_or_default(),
|
||||||
|
host_spawn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
depcheck::common::dep_pkexec,
|
depcheck::common::dep_pkexec,
|
||||||
gpu_profile::{get_amd_gpu_power_profile, GpuPowerProfile},
|
gpu_profile::{get_amd_gpu_power_profile, GpuPowerProfile},
|
||||||
|
is_flatpak::IS_FLATPAK,
|
||||||
paths::{get_data_dir, get_home_dir},
|
paths::{get_data_dir, get_home_dir},
|
||||||
profile::{LighthouseDriver, Profile, XRServiceType},
|
profile::{LighthouseDriver, Profile, XRServiceType},
|
||||||
stateless_action,
|
stateless_action,
|
||||||
|
@ -270,7 +271,7 @@ impl SimpleComponent for MainView {
|
||||||
add_css_class: "card",
|
add_css_class: "card",
|
||||||
add_css_class: "padded",
|
add_css_class: "padded",
|
||||||
#[track = "model.changed(Self::selected_profile())"]
|
#[track = "model.changed(Self::selected_profile())"]
|
||||||
set_visible: match mount_has_nosuid(&model.selected_profile.prefix) {
|
set_visible: !*IS_FLATPAK && match mount_has_nosuid(&model.selected_profile.prefix) {
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
@ -302,7 +303,34 @@ impl SimpleComponent for MainView {
|
||||||
add_css_class: "card",
|
add_css_class: "card",
|
||||||
add_css_class: "padded",
|
add_css_class: "padded",
|
||||||
#[track = "model.changed(Self::selected_profile())"]
|
#[track = "model.changed(Self::selected_profile())"]
|
||||||
set_visible: !dep_pkexec().check(),
|
set_visible: *IS_FLATPAK,
|
||||||
|
warning_heading(),
|
||||||
|
gtk::Label {
|
||||||
|
set_label: concat!(
|
||||||
|
"Envision is currently running as a Flatpak.\n",
|
||||||
|
"If Steam is running as a Flatpak, it will need to be granted certain ",
|
||||||
|
"permissions to run VR applications. Run the following command on your host ",
|
||||||
|
"terminal to grant the Steam Flatpak access to Envision's Monado socket:\n\n",
|
||||||
|
"<tt>flatpak --user override --filesystem=xdg-run/monado_comp_ipc com.valvesoftware.Steam</tt>\n\n",
|
||||||
|
"Run the following to also grant the Steam Flatpak access to Envision's data:\n\n",
|
||||||
|
"<tt>flatpak --user override --filesystem=~/.var/app/org.gabmus.envision com.valvesoftware.Steam</tt>\n\n",
|
||||||
|
),
|
||||||
|
set_use_markup: true,
|
||||||
|
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,
|
||||||
|
set_vexpand: false,
|
||||||
|
set_spacing: 12,
|
||||||
|
add_css_class: "card",
|
||||||
|
add_css_class: "padded",
|
||||||
|
#[track = "model.changed(Self::selected_profile())"]
|
||||||
|
set_visible: !*IS_FLATPAK && !dep_pkexec().check(),
|
||||||
warning_heading(),
|
warning_heading(),
|
||||||
gtk::Label {
|
gtk::Label {
|
||||||
set_label: &format!(
|
set_label: &format!(
|
||||||
|
|
|
@ -159,6 +159,7 @@ impl SimpleComponent for SteamVrCalibrationBox {
|
||||||
Some(env.clone()),
|
Some(env.clone()),
|
||||||
vrcmd.clone(),
|
vrcmd.clone(),
|
||||||
Some(vec!["--pollposes".into()]),
|
Some(vec!["--pollposes".into()]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
||||||
JobWorkerOut::Log(_) => Self::Input::NoOp,
|
JobWorkerOut::Log(_) => Self::Input::NoOp,
|
||||||
|
@ -178,6 +179,7 @@ impl SimpleComponent for SteamVrCalibrationBox {
|
||||||
Some(env),
|
Some(env),
|
||||||
vrcmd,
|
vrcmd,
|
||||||
Some(vec!["--resetroomsetup".into()]),
|
Some(vec!["--resetroomsetup".into()]),
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
JobWorker::new(jobs, sender.input_sender(), |msg| match msg {
|
||||||
JobWorkerOut::Log(_) => Self::Input::NoOp,
|
JobWorkerOut::Log(_) => Self::Input::NoOp,
|
||||||
|
|
|
@ -136,7 +136,8 @@ impl AsyncComponent for WivrnWiredStartBox {
|
||||||
"adb shell am start -a android.intent.action.VIEW -d \"wivrn+tcp://127.0.0.1\" $PACKAGE"
|
"adb shell am start -a android.intent.action.VIEW -d \"wivrn+tcp://127.0.0.1\" $PACKAGE"
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
None
|
None,
|
||||||
|
false,
|
||||||
).await {
|
).await {
|
||||||
Ok(out) if out.exit_code == 0 =>
|
Ok(out) if out.exit_code == 0 =>
|
||||||
StartClientStatus::Success
|
StartClientStatus::Success
|
||||||
|
|
24
src/util/cmd_utils.rs
Normal file
24
src/util/cmd_utils.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use std::{collections::HashMap, process::Command};
|
||||||
|
|
||||||
|
use crate::is_flatpak::IS_FLATPAK;
|
||||||
|
|
||||||
|
pub trait CommandUnsandbox {
|
||||||
|
fn new_unsandboxed(program: &str, envs: Option<HashMap<String, String>>) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandUnsandbox for Command {
|
||||||
|
fn new_unsandboxed(program: &str, envs: Option<HashMap<String, String>>) -> Self {
|
||||||
|
if *IS_FLATPAK {
|
||||||
|
let mut cmd = Command::new("flatpak-spawn");
|
||||||
|
cmd.arg("--host");
|
||||||
|
for (key, value) in envs.unwrap_or_default() {
|
||||||
|
cmd.arg(format!("--env={}={}", key, value));
|
||||||
|
}
|
||||||
|
cmd.arg(program);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
let mut cmd = Command::new(program);
|
||||||
|
cmd.envs(envs.unwrap_or_default());
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,7 +81,7 @@ pub fn setcap_cap_sys_nice_eip_cmd(profile: &Profile) -> Vec<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn setcap_cap_sys_nice_eip(profile: &Profile) {
|
pub async fn setcap_cap_sys_nice_eip(profile: &Profile) {
|
||||||
if let Err(e) = async_process("pkexec", Some(&setcap_cap_sys_nice_eip_cmd(profile)), None).await
|
if let Err(e) = async_process("pkexec", Some(&setcap_cap_sys_nice_eip_cmd(profile)), None, true).await
|
||||||
{
|
{
|
||||||
eprintln!("Error: failed running setcap: {e}");
|
eprintln!("Error: failed running setcap: {e}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod file_utils;
|
pub mod file_utils;
|
||||||
pub mod hash;
|
pub mod hash;
|
||||||
pub mod steamvr_utils;
|
pub mod steamvr_utils;
|
||||||
|
pub mod cmd_utils;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue