diff --git a/.gitignore b/.gitignore index 21fd9e12e..5b26711c5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ sciter.dll src/bridge_generated.rs *deb rustdesk +# appimage +appimage/AppDir +appimage/*.AppImage +appimage/appimage-build \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 5378d3324..ddf93a92a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ inline = [] hbbs = [] cli = [] with_rc = ["simple_rc"] +appimage = [] use_samplerate = ["samplerate"] use_rubato = ["rubato"] use_dasp = ["dasp"] diff --git a/appimage/AppImageBuilder.yml b/appimage/AppImageBuilder.yml new file mode 100644 index 000000000..81568b399 --- /dev/null +++ b/appimage/AppImageBuilder.yml @@ -0,0 +1,150 @@ +# appimage-builder recipe see https://appimage-builder.readthedocs.io for details +# Tested Linux Distro: Ubuntu 20.04 LTS +version: 1 +script: + # Remove any previous build + - rm -rf AppDir | true + # Install application dependencies + - pip3 install --system --ignore-installed --prefix=/usr --root=AppDir -r ./requirements.txt + # Download sciter.so + - mkdir -p AppDir/usr/lib/rustdesk/ + - curl https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so -o AppDir/usr/lib/rustdesk/libsciter-gtk.so + # pynput_service.py + - cp ../pynput_service.py ./AppDir/usr/lib/rustdesk + # Build rustdesk + - pushd .. && python3 inline-sciter.py && cargo build --features inline,appimage --release && popd + - mkdir -p AppDir/usr/bin + - cp ../target/release/rustdesk AppDir/usr/bin/rustdesk + # Make usr and icons dirs + - mkdir -p AppDir/usr/share/icons/hicolor/128x128 && cp ../128x128.png AppDir/usr/share/icons/hicolor/128x128/rustdesk.png + - mkdir -p AppDir/usr/share/icons/hicolor/32x32 && cp ../32x32.png AppDir/usr/share/icons/hicolor/32x32/rustdesk.png + - cp rustdesk.desktop AppDir/ + +AppDir: + path: ./AppDir + app_info: + id: rustdesk + name: RustDesk + icon: rustdesk + version: 1.2.0 + exec: usr/bin/rustdesk + exec_args: $@ + apt: + arch: + - amd64 + allow_unauthenticated: true + sources: + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal main restricted + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal universe + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates universe + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal multiverse + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-updates multiverse + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted + universe multiverse + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-security universe + - sourceline: deb http://archive.ubuntu.com/ubuntu/ focal-security multiverse + include: + - libexpat1:amd64 + - libgcc-s1:amd64 + - libgpg-error0:amd64 + - liblzma5:amd64 + - libmount1:amd64 + - libpcre3:amd64 + - libpulse0:amd64 + - libsystemd0:amd64 + - libuuid1:amd64 + - zlib1g:amd64 + - python3:amd64 + - python3-pkg-resources:amd64 + files: + include: + - /lib/x86_64-linux-gnu/libFLAC.so.8 + - /lib/x86_64-linux-gnu/libX11.so.6 + - /lib/x86_64-linux-gnu/libXau.so.6 + - /lib/x86_64-linux-gnu/libXcomposite.so.1 + - /lib/x86_64-linux-gnu/libXcursor.so.1 + - /lib/x86_64-linux-gnu/libXdamage.so.1 + - /lib/x86_64-linux-gnu/libXdmcp.so.6 + - /lib/x86_64-linux-gnu/libXext.so.6 + - /lib/x86_64-linux-gnu/libXfixes.so.3 + - /lib/x86_64-linux-gnu/libXi.so.6 + - /lib/x86_64-linux-gnu/libXinerama.so.1 + - /lib/x86_64-linux-gnu/libXrandr.so.2 + - /lib/x86_64-linux-gnu/libXrender.so.1 + - /lib/x86_64-linux-gnu/libXtst.so.6 + - /lib/x86_64-linux-gnu/libapparmor.so.1 + - /lib/x86_64-linux-gnu/libasyncns.so.0 + - /lib/x86_64-linux-gnu/libatk-1.0.so.0 + - /lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 + - /lib/x86_64-linux-gnu/libatspi.so.0 + - /lib/x86_64-linux-gnu/libbsd.so.0 + - /lib/x86_64-linux-gnu/libcairo-gobject.so.2 + - /lib/x86_64-linux-gnu/libcairo.so.2 + - /lib/x86_64-linux-gnu/libdatrie.so.1 + - /lib/x86_64-linux-gnu/libepoxy.so.0 + - /lib/x86_64-linux-gnu/libffi.so.7 + - /lib/x86_64-linux-gnu/libfontconfig.so.1 + - /lib/x86_64-linux-gnu/libfreetype.so.6 + - /lib/x86_64-linux-gnu/libfribidi.so.0 + - /lib/x86_64-linux-gnu/libgcrypt.so.20 + - /lib/x86_64-linux-gnu/libgdk-3.so.0 + - /lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 + - /lib/x86_64-linux-gnu/libgio-2.0.so.0 + - /lib/x86_64-linux-gnu/libglib-2.0.so.0 + - /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 + - /lib/x86_64-linux-gnu/libgobject-2.0.so.0 + - /lib/x86_64-linux-gnu/libgraphite2.so.3 + - /lib/x86_64-linux-gnu/libgtk-3.so.0 + - /lib/x86_64-linux-gnu/libharfbuzz.so.0 + - /lib/x86_64-linux-gnu/liblz4.so.1 + - /lib/x86_64-linux-gnu/libogg.so.0 + - /lib/x86_64-linux-gnu/libpango-1.0.so.0 + - /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 + - /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 + - /lib/x86_64-linux-gnu/libpcre2-8.so.0 + - /lib/x86_64-linux-gnu/libpixman-1.so.0 + - /lib/x86_64-linux-gnu/libpng16.so.16 + - /lib/x86_64-linux-gnu/libpulse-simple.so.0 + - /lib/x86_64-linux-gnu/libpulse.so.0 + - /lib/x86_64-linux-gnu/libsndfile.so.1 + - /lib/x86_64-linux-gnu/libthai.so.0 + - /lib/x86_64-linux-gnu/libvorbis.so.0 + - /lib/x86_64-linux-gnu/libvorbisenc.so.2 + - /lib/x86_64-linux-gnu/libwayland-client.so.0 + - /lib/x86_64-linux-gnu/libwayland-cursor.so.0 + - /lib/x86_64-linux-gnu/libwayland-egl.so.1 + - /lib/x86_64-linux-gnu/libwrap.so.0 + - /lib/x86_64-linux-gnu/libxcb-randr.so.0 + - /lib/x86_64-linux-gnu/libxdo.so.3 + - /lib/x86_64-linux-gnu/libxkbcommon.so.0 + exclude: + - usr/share/man + - usr/share/doc/*/README.* + - usr/share/doc/*/changelog.* + - usr/share/doc/*/NEWS.* + - usr/share/doc/*/TODO.* + runtime: + env: + PYTHONHOME: '${APPDIR}/usr' + PYTHONPATH: '${APPDIR}/usr/lib/python3.8/site-packages' + test: + fedora-30: + image: appimagecrafters/tests-env:fedora-30 + command: ./AppRun + debian-stable: + image: appimagecrafters/tests-env:debian-stable + command: ./AppRun + archlinux-latest: + image: appimagecrafters/tests-env:archlinux-latest + command: ./AppRun + centos-7: + image: appimagecrafters/tests-env:centos-7 + command: ./AppRun + ubuntu-xenial: + image: appimagecrafters/tests-env:ubuntu-xenial + command: ./AppRun +AppImage: + arch: x86_64 + update-information: guess diff --git a/appimage/README.md b/appimage/README.md new file mode 100644 index 000000000..1dcfa0b35 --- /dev/null +++ b/appimage/README.md @@ -0,0 +1,20 @@ +# How to build and run RustDesk in AppImage + +Begin by installing `appimage-builder` and predependencies mentioned in official website. + +Assume that `appimage-builder` is setup correctly, run commands below, `bash` or `zsh` is recommended: + +```bash +cd /path/to/rustdesk_root +./build_appimage.py +``` + +After a success package, you can see the message in console like: + +```shell +INFO:root:AppImage created successfully +``` + +The AppImage package is shown in `./appimage/RustDesk-VERSION-TARGET_PLATFORM.AppImage`. + +Note: AppImage version of rustdesk is an early version which requires more test. If you find problems, please open an issue. \ No newline at end of file diff --git a/appimage/requirements.txt b/appimage/requirements.txt new file mode 100644 index 000000000..d632797e5 --- /dev/null +++ b/appimage/requirements.txt @@ -0,0 +1 @@ +pynput \ No newline at end of file diff --git a/appimage/rustdesk.desktop b/appimage/rustdesk.desktop new file mode 100644 index 000000000..f2e8b80b7 --- /dev/null +++ b/appimage/rustdesk.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Version=1.2.0 +Name=RustDesk +GenericName=Remote Desktop +Comment=Remote Desktop +Exec=rustdesk +Icon=rustdesk +Terminal=false +Type=Application +StartupNotify=true +Categories=Other; +Keywords=internet; +Actions=new-window; + +X-Desktop-File-Install-Version=0.23 + +[Desktop Action new-window] +Name=Open a New Window + diff --git a/build_appimage.py b/build_appimage.py new file mode 100755 index 000000000..a4e1a1cb7 --- /dev/null +++ b/build_appimage.py @@ -0,0 +1,22 @@ +#!/usr/bin/python3 +import os + +def get_version(): + with open("Cargo.toml") as fh: + for line in fh: + if line.startswith("version"): + return line.replace("version", "").replace("=", "").replace('"', '').strip() + return '' + +if __name__ == '__main__': + # check version + version = get_version() + os.chdir("appimage") + os.system("sed -i 's/^Version=.*/Version=%s/g' rustdesk.desktop" % version) + # build appimage + ret = os.system("appimage-builder --recipe AppImageBuilder.yml --skip-test") + if ret == 0: + print("RustDesk AppImage build success :)") + print("Check AppImage in '/path/to/rustdesk/appimage/RustDesk-VERSION-TARGET_PLATFORM.AppImage'") + else: + print("RustDesk AppImage build failed :(") diff --git a/libs/enigo/src/linux.rs b/libs/enigo/src/linux.rs index 8881d26d5..adfe9507c 100644 --- a/libs/enigo/src/linux.rs +++ b/libs/enigo/src/linux.rs @@ -491,7 +491,11 @@ fn start_pynput_service(rx: mpsc::Receiver<(PyMsg, bool)>) { if !std::path::Path::new(&py).exists() { py = "/usr/lib/rustdesk/pynput_service.py".to_owned(); if !std::path::Path::new(&py).exists() { - log::error!("{} not exits", py); + // enigo libs, not rustdesk root project, so skip using appimage features + py = std::env::var("APPDIR").unwrap_or("".to_string()) + "/usr/lib/rustdesk/pynput_service.py"; + if !std::path::Path::new(&py).exists() { + log::error!("{} not exists", py); + } } } } diff --git a/rustdesk.desktop b/rustdesk.desktop index 8bdbe06e0..11c7daad0 100644 --- a/rustdesk.desktop +++ b/rustdesk.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -Version=1.0 +Version=1.2.0 Name=RustDesk GenericName=Remote Desktop Comment=Remote Desktop diff --git a/src/common.rs b/src/common.rs index 39503ace6..972f33500 100644 --- a/src/common.rs +++ b/src/common.rs @@ -14,7 +14,7 @@ use hbb_common::{ }; #[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))] use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all}; -use std::sync::{Arc, Mutex}; +use std::{sync::{Arc, Mutex}, path::Path}; pub const CLIPBOARD_NAME: &'static str = "clipboard"; pub const CLIPBOARD_INTERVAL: u64 = 333; @@ -377,8 +377,18 @@ pub fn get_time() -> i64 { } pub fn run_me>(args: Vec) -> std::io::Result { - let cmd = std::env::current_exe()?; - return std::process::Command::new(cmd).args(&args).spawn(); + #[cfg(not(feature = "appimage"))] + { + let cmd = std::env::current_exe()?; + return std::process::Command::new(cmd).args(&args).spawn(); + } + #[cfg(feature = "appimage")] + { + let appdir = std::env::var("APPDIR").unwrap(); + let appimage_cmd = Path::new(&appdir).join("AppRun"); + log::info!("path: {:?}", appimage_cmd); + return std::process::Command::new(appimage_cmd).args(&args).spawn(); + } } pub fn username() -> String { diff --git a/src/ui.rs b/src/ui.rs index 6a084552d..7b953e700 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -56,7 +56,13 @@ pub fn start(args: &mut [String]) { macos::show_dock(); } #[cfg(all(target_os = "linux", feature = "inline"))] - sciter::set_library("/usr/lib/rustdesk/libsciter-gtk.so").ok(); + { + #[cfg(feature = "appimage")] + let prefix = std::env::var("APPDIR").unwrap_or("".to_string()); + #[cfg(not(feature = "appimage"))] + let prefix = "".to_string(); + sciter::set_library(&(prefix + "/usr/lib/rustdesk/libsciter-gtk.so")).ok(); + } // https://github.com/c-smile/sciter-sdk/blob/master/include/sciter-x-types.h // https://github.com/rustdesk/rustdesk/issues/132#issuecomment-886069737 #[cfg(windows)]