diff --git a/.github/workflows/build-appimage.yml b/.github/workflows/build-appimage.yml index a925afb..b567f98 100644 --- a/.github/workflows/build-appimage.yml +++ b/.github/workflows/build-appimage.yml @@ -21,30 +21,13 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.9 - name: Prepare Environment run: | - sudo add-apt-repository -syn universe - sudo add-apt-repository -syn ppa:pipewire-debian/pipewire-upstream || sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 25088A0359807596 - sudo apt-get update - sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev - rustup update - - test -f linuxdeploy-x86_64.AppImage || wget -q "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" - chmod +x linuxdeploy-x86_64.AppImage - - test -d ${APPDIR} && rm -rf ${APPDIR} - mkdir -p ${APPDIR}/usr/bin - + .github/workflows/scripts/appimage_prepare_env.sh - name: Cargo Build run: | - cargo build --release - mv target/release/wlx-overlay-s ${APPDIR}/usr/bin - chmod +x ${APPDIR}/usr/bin/wlx-overlay-s - + .github/workflows/scripts/appimage_build_wlx.sh - name: Package AppImage run: | - export VERSION=$GITHUB_REF_NAME - ./linuxdeploy-x86_64.AppImage -dwlx-overlay-s.desktop -iwlx-overlay-s.png --appdir=${APPDIR} --output appimage --exclude-library '*libpipewire*' - mv WlxOverlay-S-$VERSION-x86_64.AppImage WlxOverlay-S-x86_64.AppImage - + .github/workflows/scripts/appimage_package.sh - name: Upload AppImage uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/build-full-appimage.yml b/.github/workflows/build-full-appimage.yml new file mode 100644 index 0000000..ad9df73 --- /dev/null +++ b/.github/workflows/build-full-appimage.yml @@ -0,0 +1,38 @@ +name: Build AppImage (with WayVR Dashboard) + +on: + push: + branches: + - 'main' + - 'staging' + +env: + APPDIR: WlxOverlay-S-Full.AppDir + CARGO_TERM_COLOR: always + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + +jobs: + build_appimage: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.9 + - name: Prepare Environment + run: | + .github/workflows/scripts/appimage_prepare_env.sh + - name: Cargo Build + run: | + .github/workflows/scripts/appimage_build_wlx.sh + - name: Build WayVR Dashboard + run: | + .github/workflows/scripts/appimage_build_wayvr_dashboard.sh + - name: Package AppImage + run: | + .github/workflows/scripts/appimage_package_full.sh + - name: Upload AppImage + uses: actions/upload-artifact@v4 + with: + name: WlxOverlay-S-Full-${{ github.ref_name }}-x86_64.AppImage + path: ./WlxOverlay-S-Full-x86_64.AppImage diff --git a/.github/workflows/scripts/appimage_build_wayvr_dashboard.sh b/.github/workflows/scripts/appimage_build_wayvr_dashboard.sh new file mode 100755 index 0000000..e12e954 --- /dev/null +++ b/.github/workflows/scripts/appimage_build_wayvr_dashboard.sh @@ -0,0 +1,34 @@ +#!/bin/sh +git clone --depth=1 https://github.com/olekolek1000/wayvr-dashboard.git wayvr-dashboard + +WLX_DIR=$(realpath $(pwd)) + +cd wayvr-dashboard +.github/workflows/build.sh + +# See https://github.com/olekolek1000/wayvr-dashboard/blob/master/.github/workflows/appimage.sh +cd .. +cd ${APPDIR} + +# Fix webkit +echo "Copying webkit runtime executables" + +# Copy runtime executables +find -L /usr/lib /usr/libexec -name WebKitNetworkProcess -exec mkdir -p . ';' -exec cp -v --parents '{}' . ';' || true +find -L /usr/lib /usr/libexec -name WebKitWebProcess -exec mkdir -p . ';' -exec cp -v --parents '{}' . ';' || true +find -L /usr/lib /usr/libexec -name libwebkit2gtkinjectedbundle.so -exec mkdir -p . ';' -exec cp --parents '{}' . ';' || true + +echo "Patching webkit lib" + +# Patch libwebkit .so file: Replace 4 bytes containing "/usr" into "././". Required! +TARGET_WEBKIT_SO="./usr/lib/libwebkit2gtk-4.1.so.0" +cp /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.1.so.0 ${TARGET_WEBKIT_SO} +sed -i -e "s|/usr|././|g" "${TARGET_WEBKIT_SO}" + +cd ${WLX_DIR} + +DASH_PATH="${WLX_DIR}/wayvr-dashboard/temp/wayvr-dashboard" +chmod +x ${DASH_PATH} + +# Put resulting executable into wlx AppDir +cp ${DASH_PATH} ${APPDIR}/usr/bin/wayvr-dashboard \ No newline at end of file diff --git a/.github/workflows/scripts/appimage_build_wlx.sh b/.github/workflows/scripts/appimage_build_wlx.sh new file mode 100755 index 0000000..c8ae1f4 --- /dev/null +++ b/.github/workflows/scripts/appimage_build_wlx.sh @@ -0,0 +1,4 @@ +#!/bin/sh +cargo build --release +mv target/release/wlx-overlay-s ${APPDIR}/usr/bin +chmod +x ${APPDIR}/usr/bin/wlx-overlay-s \ No newline at end of file diff --git a/.github/workflows/scripts/appimage_package.sh b/.github/workflows/scripts/appimage_package.sh new file mode 100755 index 0000000..aed60cd --- /dev/null +++ b/.github/workflows/scripts/appimage_package.sh @@ -0,0 +1,4 @@ +#!/bin/sh +export VERSION=$GITHUB_REF_NAME +./linuxdeploy-x86_64.AppImage -dwlx-overlay-s.desktop -iwlx-overlay-s.png --appdir=${APPDIR} --output appimage --exclude-library '*libpipewire*' +mv WlxOverlay-S-$VERSION-x86_64.AppImage WlxOverlay-S-x86_64.AppImage \ No newline at end of file diff --git a/.github/workflows/scripts/appimage_package_full.sh b/.github/workflows/scripts/appimage_package_full.sh new file mode 100755 index 0000000..f55b817 --- /dev/null +++ b/.github/workflows/scripts/appimage_package_full.sh @@ -0,0 +1,4 @@ +#!/bin/sh +export VERSION=$GITHUB_REF_NAME +./linuxdeploy-x86_64.AppImage -dwlx-overlay-s.desktop -iwlx-overlay-s.png --appdir=${APPDIR} --output appimage --exclude-library '*libpipewire*' +mv WlxOverlay-S-$VERSION-x86_64.AppImage WlxOverlay-S-Full-x86_64.AppImage \ No newline at end of file diff --git a/.github/workflows/scripts/appimage_prepare_env.sh b/.github/workflows/scripts/appimage_prepare_env.sh new file mode 100755 index 0000000..73db606 --- /dev/null +++ b/.github/workflows/scripts/appimage_prepare_env.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +sudo add-apt-repository -syn universe +sudo add-apt-repository -syn ppa:pipewire-debian/pipewire-upstream || sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 25088A0359807596 +sudo apt-get update +sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev +rustup update + +test -f linuxdeploy-x86_64.AppImage || wget -q "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" +chmod +x linuxdeploy-x86_64.AppImage + +test -d ${APPDIR} && rm -rf ${APPDIR} +mkdir -p ${APPDIR}/usr/bin \ No newline at end of file diff --git a/src/backend/wayvr/display.rs b/src/backend/wayvr/display.rs index 0bd58b6..8deffae 100644 --- a/src/backend/wayvr/display.rs +++ b/src/backend/wayvr/display.rs @@ -556,6 +556,7 @@ impl Display { exec_path: &str, args: &[&str], env: &[(&str, &str)], + working_dir: Option<&str>, ) -> anyhow::Result { log::info!("Spawning subprocess with exec path \"{exec_path}\""); @@ -564,6 +565,9 @@ impl Display { let mut cmd = std::process::Command::new(exec_path); self.configure_env(&mut cmd, auth_key.as_str()); cmd.args(args); + if let Some(working_dir) = working_dir { + cmd.current_dir(working_dir); + } for e in env { cmd.env(e.0, e.1); diff --git a/src/backend/wayvr/mod.rs b/src/backend/wayvr/mod.rs index 1b3b5ec..4522c7a 100644 --- a/src/backend/wayvr/mod.rs +++ b/src/backend/wayvr/mod.rs @@ -684,6 +684,7 @@ impl WayVRState { exec_path: &str, args: &[&str], env: &[(&str, &str)], + working_dir: Option<&str>, userdata: HashMap, ) -> anyhow::Result { let display = self @@ -691,7 +692,7 @@ impl WayVRState { .get_mut(&display_handle) .ok_or_else(|| anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; - let res = display.spawn_process(exec_path, args, env)?; + let res = display.spawn_process(exec_path, args, env, working_dir)?; let handle = self .processes @@ -702,6 +703,7 @@ impl WayVRState { exec_path: String::from(exec_path), userdata, args: args.iter().map(|x| String::from(*x)).collect(), + working_dir: working_dir.map(String::from), env: env .iter() .map(|(a, b)| (String::from(*a), String::from(*b))) diff --git a/src/backend/wayvr/process.rs b/src/backend/wayvr/process.rs index b87d3d4..f0392da 100644 --- a/src/backend/wayvr/process.rs +++ b/src/backend/wayvr/process.rs @@ -16,6 +16,7 @@ pub struct WayVRProcess { pub exec_path: String, pub args: Vec, pub env: Vec<(String, String)>, + pub working_dir: Option, pub userdata: HashMap, } diff --git a/src/backend/wayvr/server_ipc.rs b/src/backend/wayvr/server_ipc.rs index 6545898..2e54529 100644 --- a/src/backend/wayvr/server_ipc.rs +++ b/src/backend/wayvr/server_ipc.rs @@ -365,6 +365,7 @@ impl Connection { &packet_params.exec, &args_vec, &env_vec, + None, packet_params.userdata, ); diff --git a/src/config_wayvr.rs b/src/config_wayvr.rs index d8e44fe..ae038ae 100644 --- a/src/config_wayvr.rs +++ b/src/config_wayvr.rs @@ -19,7 +19,7 @@ use crate::{ config::load_config_with_conf_d, config_io, gui::modular::button::WayVRAction, - overlays::wayvr::WayVRData, + overlays::wayvr::{executable_exists_in_path, WayVRData}, }; // Flat version of RelativeTo @@ -120,6 +120,7 @@ fn def_blit_method() -> String { #[derive(Clone, Deserialize, Serialize)] pub struct WayVRDashboard { pub exec: String, + pub working_dir: Option, pub args: Option, pub env: Option>, } @@ -234,6 +235,21 @@ impl WayVRConfig { } } +fn get_default_dashboard_exec() -> ( + String, /* exec path */ + Option, /* working directory */ +) { + if let Ok(appdir) = std::env::var("APPDIR") { + // Running in AppImage + let embedded_path = format!("{appdir}/usr/bin/wayvr-dashboard"); + if executable_exists_in_path(&embedded_path) { + log::info!("Using WayVR Dashboard from AppDir: {embedded_path}"); + return (embedded_path, Some(format!("{appdir}/usr"))); + } + } + (String::from("wayvr-dashboard"), None) +} + pub fn load_wayvr() -> WayVRConfig { let config_root_path = config_io::ConfigRoot::WayVR.ensure_dir(); log::info!("WayVR Config root path: {}", config_root_path.display()); @@ -242,5 +258,19 @@ pub fn load_wayvr() -> WayVRConfig { config_io::ConfigRoot::WayVR.get_conf_d_path().display() ); - load_config_with_conf_d::("wayvr.yaml", config_io::ConfigRoot::WayVR) + let mut conf = + load_config_with_conf_d::("wayvr.yaml", config_io::ConfigRoot::WayVR); + + if conf.dashboard.is_none() { + let (exec, working_dir) = get_default_dashboard_exec(); + + conf.dashboard = Some(WayVRDashboard { + args: None, + env: None, + exec, + working_dir, + }); + } + + conf } diff --git a/src/overlays/wayvr.rs b/src/overlays/wayvr.rs index 67e615e..f06cfcf 100644 --- a/src/overlays/wayvr.rs +++ b/src/overlays/wayvr.rs @@ -249,7 +249,7 @@ fn get_or_create_display_by_name( Ok(disp_handle) } -fn executable_exists_in_path(command: &str) -> bool { +pub fn executable_exists_in_path(command: &str) -> bool { let Ok(path) = std::env::var("PATH") else { return false; // very unlikely to happen }; @@ -270,14 +270,9 @@ fn toggle_dashboard( where O: Default, { - let conf_dash = app.session.wayvr_config.dashboard.clone().map_or_else( - || config_wayvr::WayVRDashboard { - exec: String::from("wayvr-dashboard"), - args: None, - env: None, - }, - |conf| conf, - ); + let Some(conf_dash) = app.session.wayvr_config.dashboard.clone() else { + anyhow::bail!("Dashboard is not configured"); + }; if !wayvr.dashboard_executed && !executable_exists_in_path(&conf_dash.exec) { anyhow::bail!("Executable \"{}\" not found", &conf_dash.exec); @@ -317,10 +312,6 @@ where overlay.state.z_order = Z_ORDER_DASHBOARD; overlay.state.reset(app, true); - let Some(conf_dash) = &app.session.wayvr_config.dashboard else { - unreachable!(); /* safe, not possible to trigger */ - }; - overlays.add(overlay); let args_vec = &conf_dash @@ -342,6 +333,7 @@ where &conf_dash.exec, args_vec, env_vec, + conf_dash.working_dir.as_deref(), userdata, )?; @@ -879,6 +871,7 @@ where &app_entry.exec, args_vec, env_vec, + None, HashMap::default(), )?;