diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 7544400..069e488 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -24,7 +24,7 @@ jobs: - name: Download Dependencies run: | sudo apt update - sudo apt install -y ffmpeg libudev-dev libevdev-dev libhidapi-dev libpipewire-0.3-dev libpipewire-0.3-modules libpipewire-0.3-0 x264 libx264-dev libclang-dev clang llvm-dev libasound2-dev libxrandr-dev libxcb-randr0-dev libxdo-dev libxcb-shm0-dev cmake + sudo apt install -y ffmpeg libudev-dev libevdev-dev libhidapi-dev libpipewire-0.3-dev libpipewire-0.3-modules libpipewire-0.3-0 x264 libx264-dev libclang-dev clang llvm-dev libasound2-dev libxrandr-dev libxcb-randr0-dev libxcb-shm0-dev cmake cargo install cargo-deb - name: Build Server run: | @@ -69,7 +69,7 @@ jobs: - name: Download Dependencies run: | sudo apt update - sudo NEEDRESTART_MODE=a apt install -y yasm ffmpeg libudev-dev libevdev-dev libhidapi-dev libpipewire-0.3-dev libpipewire-0.3-modules libpipewire-0.3-0 x264 libx264-dev libclang-dev clang llvm-dev libasound2-dev libxrandr-dev libxcb-randr0-dev libxdo-dev libxcb-shm0-dev + sudo NEEDRESTART_MODE=a apt install -y yasm ffmpeg libudev-dev libevdev-dev libhidapi-dev libpipewire-0.3-dev libpipewire-0.3-modules libpipewire-0.3-0 x264 libx264-dev libclang-dev clang llvm-dev libasound2-dev libxrandr-dev libxcb-randr0-dev libxcb-shm0-dev cargo install cargo-deb - name: Build Server run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index e616bbb..21fcbdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog All notable changes to this project are documented in this file. +## 0.1.18 - 2024-02-16 + +- Logout detection with 1 second frequency +- No longer dependent on libxdo + ## 0.1.17 - 2024-02-10 - Systemd service works again! (well... at least partially) diff --git a/Cargo.lock b/Cargo.lock index ab6507d..a8578d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -543,12 +543,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base-x" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" - [[package]] name = "base64" version = "0.22.1" @@ -680,16 +674,6 @@ dependencies = [ "objc2 0.4.1", ] -[[package]] -name = "block2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f" -dependencies = [ - "block-sys", - "objc2 0.5.2", -] - [[package]] name = "block2" version = "0.5.1" @@ -924,7 +908,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -946,7 +930,7 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.3", + "libloading", ] [[package]] @@ -1014,9 +998,9 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.2", - "foreign-types 0.5.0", + "foreign-types", "libc", "objc", ] @@ -1029,8 +1013,8 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "libc", "objc", ] @@ -1103,12 +1087,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "const_fn" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" - [[package]] name = "convert_case" version = "0.4.0" @@ -1157,35 +1135,45 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.22.3" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", "libc", ] [[package]] name = "core-graphics" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.5.0", + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", + "foreign-types", "libc", ] @@ -1196,7 +1184,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -1206,9 +1205,9 @@ version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.2", - "foreign-types 0.5.0", + "foreign-types", "libc", ] @@ -1476,7 +1475,7 @@ dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version 0.4.0", + "rustc_version", "syn 2.0.66", ] @@ -1523,12 +1522,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "dispatch" version = "0.2.0" @@ -1552,7 +1545,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.3", + "libloading", ] [[package]] @@ -1636,18 +1629,21 @@ dependencies = [ [[package]] name = "enigo" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0087a01fc8591217447d28005379fb5a183683cc83f0a4707af28cc6603f70fb" +checksum = "0cf6f550bbbdd5fe66f39d429cb2604bcdacbf00dca0f5bbe2e9306a0009b7c6" dependencies = [ - "core-graphics 0.23.2", - "foreign-types-shared 0.3.1", - "icrate 0.1.2", + "core-foundation 0.10.0", + "core-graphics 0.24.0", + "foreign-types-shared", "libc", "log", "objc2 0.5.2", - "windows 0.56.0", - "xkbcommon", + "objc2-app-kit", + "objc2-foundation", + "windows 0.58.0", + "x11rb 0.13.1", + "xkbcommon 0.8.0", "xkeysym", ] @@ -1852,7 +1848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset 0.9.1", - "rustc_version 0.4.0", + "rustc_version", ] [[package]] @@ -1956,15 +1952,6 @@ dependencies = [ "ttf-parser", ] -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -1972,7 +1959,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -1986,12 +1973,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -2242,12 +2223,12 @@ dependencies = [ "bitflags 2.6.0", "cfg_aliases 0.2.1", "cgl", - "core-foundation", + "core-foundation 0.9.4", "dispatch", "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "libloading 0.8.3", + "libloading", "objc2 0.5.2", "objc2-app-kit", "objc2-foundation", @@ -2343,7 +2324,7 @@ checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" dependencies = [ "atomic-polyfill", "hash32", - "rustc_version 0.4.0", + "rustc_version", "spin 0.9.8", "stable_deref_trait", ] @@ -2412,7 +2393,7 @@ dependencies = [ "memmap2 0.9.4", "nix 0.27.1", "raw-window-handle", - "xkbcommon", + "xkbcommon 0.7.0", ] [[package]] @@ -2494,7 +2475,7 @@ dependencies = [ "cfg-if 1.0.0", "derive_more", "fontdb", - "libloading 0.8.3", + "libloading", ] [[package]] @@ -2591,7 +2572,7 @@ checksum = "6c7ecc7713bc6d074b1ea10a3bba71ca006f0de6159ca7662c9a91a5e63d1be5" dependencies = [ "cfg-if 1.0.0", "const-field-offset", - "core-foundation", + "core-foundation 0.9.4", "core-text", "derive_more", "dwrote", @@ -2625,10 +2606,10 @@ dependencies = [ "cfg_aliases 0.2.1", "cocoa", "const-field-offset", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "derive_more", - "foreign-types 0.5.0", + "foreign-types", "glow", "glutin", "i-slint-common", @@ -2682,16 +2663,6 @@ dependencies = [ "objc2 0.4.1", ] -[[package]] -name = "icrate" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb69199826926eb864697bddd27f73d9fddcffc004f5733131e15b465e30642" -dependencies = [ - "block2 0.4.0", - "objc2 0.5.2", -] - [[package]] name = "icu_collections" version = "1.5.0" @@ -3119,16 +3090,6 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - [[package]] name = "libloading" version = "0.8.3" @@ -3136,7 +3097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3392,8 +3353,8 @@ checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" dependencies = [ "bitflags 2.6.0", "block", - "core-graphics-types", - "foreign-types 0.5.0", + "core-graphics-types 0.1.3", + "foreign-types", "log", "objc", "paste", @@ -3438,23 +3399,9 @@ dependencies = [ "nix 0.26.4", ] -[[package]] -name = "mouse-rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a0952882cad9c5f95a425506b09330fe04dd92b5d0c0ca1ed0c0c09d5a12bf" -dependencies = [ - "core-graphics 0.22.3", - "libc", - "libloading 0.6.7", - "time 0.2.27", - "winapi 0.3.9", - "x11", -] - [[package]] name = "mrial_fs" -version = "0.1.17" +version = "0.1.18" dependencies = [ "dirs", "log", @@ -3466,7 +3413,7 @@ dependencies = [ [[package]] name = "mrial_player" -version = "0.1.17" +version = "0.1.18" dependencies = [ "base64", "chacha20poly1305", @@ -3492,7 +3439,7 @@ dependencies = [ [[package]] name = "mrial_proto" -version = "0.1.17" +version = "0.1.18" dependencies = [ "chacha20poly1305", "log", @@ -3505,7 +3452,7 @@ dependencies = [ [[package]] name = "mrial_server" -version = "0.1.17" +version = "0.1.18" dependencies = [ "base64", "cfg-if 0.1.10", @@ -3517,7 +3464,6 @@ dependencies = [ "libyuv-sys", "log", "mouse-keyboard-input", - "mouse-rs", "mrial_fs", "mrial_proto", "pipewire", @@ -4111,7 +4057,7 @@ dependencies = [ "libc", "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4372,12 +4318,6 @@ dependencies = [ "toml_edit 0.21.1", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.85" @@ -4404,7 +4344,7 @@ checksum = "d405b0934e4176fb264d6ca597e5c8c2fba562fa155cba681ca160c1eb7edc6e" dependencies = [ "cpp", "cpp_build", - "semver 1.0.23", + "semver", ] [[package]] @@ -4641,22 +4581,13 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.23", + "semver", ] [[package]] @@ -4748,8 +4679,6 @@ dependencies = [ "block", "cfg-if 0.1.10", "libc", - "log", - "pretty_env_logger", "winapi 0.2.8", ] @@ -4779,27 +4708,12 @@ dependencies = [ "tiny-skia", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "seq-macro" version = "0.3.5" @@ -4857,15 +4771,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - [[package]] name = "sha1" version = "0.10.6" @@ -4877,12 +4782,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.10.8" @@ -5136,7 +5035,7 @@ dependencies = [ "cfg_aliases 0.2.1", "core-graphics 0.23.2", "fastrand 2.1.0", - "foreign-types 0.5.0", + "foreign-types", "js-sys", "log", "memmap2 0.9.4", @@ -5206,70 +5105,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1 0.6.1", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "str-buf" version = "1.0.6" @@ -5493,21 +5334,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", - "time-macros", - "version_check", - "winapi 0.3.9", -] - [[package]] name = "time" version = "0.3.36" @@ -5527,29 +5353,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn 1.0.109", -] - [[package]] name = "tiny-skia" version = "0.11.4" @@ -5584,7 +5387,7 @@ checksum = "1d52f22673960ad13af14ff4025997312def1223bfa7c8e4949d099e6b3d5d1c" dependencies = [ "as-raw-xcb-connection", "ctor-lite", - "libloading 0.8.3", + "libloading", "pkg-config", "tracing", ] @@ -6343,7 +6146,7 @@ dependencies = [ "windows-core 0.54.0", "windows-implement 0.53.0", "windows-interface 0.53.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6353,7 +6156,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ "windows-core 0.56.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", ] [[package]] @@ -6362,7 +6175,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6371,8 +6184,8 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", ] [[package]] @@ -6383,8 +6196,21 @@ checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" dependencies = [ "windows-implement 0.56.0", "windows-interface 0.56.0", - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", ] [[package]] @@ -6409,6 +6235,17 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "windows-interface" version = "0.53.0" @@ -6431,13 +6268,43 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "windows-result" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -6464,7 +6331,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6499,18 +6366,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -6527,9 +6394,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -6545,9 +6412,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -6563,15 +6430,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -6587,9 +6454,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -6605,9 +6472,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -6623,9 +6490,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -6641,9 +6508,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" @@ -6658,10 +6525,10 @@ dependencies = [ "bytemuck", "calloop 0.12.4", "cfg_aliases 0.1.1", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.2", "cursor-icon", - "icrate 0.0.4", + "icrate", "js-sys", "libc", "log", @@ -6708,7 +6575,7 @@ dependencies = [ "calloop 0.13.0", "cfg_aliases 0.2.1", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.2", "cursor-icon", "dpi", @@ -6864,7 +6731,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname 0.4.3", "libc", - "libloading 0.8.3", + "libloading", "once_cell", "rustix 0.38.34", "x11rb-protocol 0.13.1", @@ -6938,6 +6805,17 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "xkbcommon" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" +dependencies = [ + "libc", + "memmap2 0.9.4", + "xkeysym", +] + [[package]] name = "xkbcommon-dl" version = "0.4.2" @@ -6979,7 +6857,7 @@ dependencies = [ "itertools 0.10.5", "libc", "thiserror", - "time 0.3.36", + "time", "x11", ] @@ -7046,7 +6924,7 @@ dependencies = [ "rand", "serde", "serde_repr", - "sha1 0.10.6", + "sha1", "static_assertions", "tracing", "uds_windows", diff --git a/Cargo.toml b/Cargo.toml index 822b1cb..26d9cc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ members = [ exclude = [ "libs" ] [workspace.package] -version = "0.1.17" +version = "0.1.18" authors = ["Mahit Mehta", "Marco Ngai"] license = "GPL-3.0-only" edition = "2021" diff --git a/mrial_player/ui/screens/video.slint b/mrial_player/ui/screens/video.slint index 7dc39ea..3a70113 100644 --- a/mrial_player/ui/screens/video.slint +++ b/mrial_player/ui/screens/video.slint @@ -23,6 +23,9 @@ export component VideoScreen inherits Screen { in-out property cp_button_attached: false; property loading_animation_duration: 1500ms; + private property prev_x: 0; + private property prev_y: 0; + background: black; image_container := VerticalBox { @@ -61,7 +64,14 @@ export component VideoScreen inherits Screen { VideoFunctions.click(video_ta.mouse-x, video_ta.mouse-y, event.button); } else if (event.kind == PointerEventKind.move) { + if (prev_x == video_ta.mouse-x && prev_y == video_ta.mouse-y) { + return; + } + VideoFunctions.mouse_move(video_ta.mouse-x, video_ta.mouse-y, false); + + prev_x = video_ta.mouse-x; + prev_y = video_ta.mouse-y; } } moved => { diff --git a/mrial_server/Cargo.toml b/mrial_server/Cargo.toml index 577b925..9cc747c 100644 --- a/mrial_server/Cargo.toml +++ b/mrial_server/Cargo.toml @@ -12,8 +12,7 @@ futures = { version = "0.3.29", features = ["thread-pool", "executor"]} # scrap = "0.5" scrap = { path = "../libs/scrap" } tokio = { version = "1.34.0", features = ["full"]} -mouse-rs = "0.4.2" -enigo = "0.2.0-rc2" +enigo = { version = "0.3.0", features = ["x11rb"] } cfg-if = "0.1" mrial_proto = { path = "../libs/mrial_proto" } mrial_fs = { path = "../libs/mrial_fs" } @@ -27,7 +26,7 @@ log = "0.4.21" rand = "0.8.5" base64 = "0.22.1" chacha20poly1305 = "0.10.1" - + [target."cfg(target_os = \"linux\")".dependencies] libyuv-sys = { path = "../libs/libyuv-sys" } pipewire = { path = "../libs/pipewire-rs/pipewire", features = ["v0_3_44"] } diff --git a/mrial_server/src/conn/mod.rs b/mrial_server/src/conn/mod.rs index 7f7842f..924ab0e 100644 --- a/mrial_server/src/conn/mod.rs +++ b/mrial_server/src/conn/mod.rs @@ -196,7 +196,6 @@ impl Connection { } }; - // TODO: Validate User Credentials debug!("Client Shake AE by User: {:?}", payload.username); match self.users.load() { Ok(_) => { @@ -281,7 +280,8 @@ impl Connection { let mut rng = rand::thread_rng(); let bits = 2048; - let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("Failed to Generate RSA Key Pair"); + let priv_key = RsaPrivateKey::new(&mut rng, bits) + .expect("Failed to Generate RSA Key Pair"); let pub_key = RsaPublicKey::from(&priv_key); let pub_key_str = pub_key.to_pkcs1_pem(rsa::pkcs1::LineEnding::LF).unwrap(); diff --git a/mrial_server/src/events/mod.rs b/mrial_server/src/events/mod.rs index a825c03..8842c89 100644 --- a/mrial_server/src/events/mod.rs +++ b/mrial_server/src/events/mod.rs @@ -1,10 +1,9 @@ -use std::{net::SocketAddr, thread}; +use std::{net::SocketAddr, thread::{self, JoinHandle}}; use enigo::{ - Direction::{Press, Release}, - Enigo, Keyboard, Mouse, Settings, + Direction::{Press, Release}, Enigo, InputError, Keyboard, Mouse, Settings }; -use kanal::Sender; +use kanal::{Receiver, Sender}; use log::debug; use mrial_proto::{ input::*, @@ -19,9 +18,10 @@ use super::{conn::Connection, VideoServerAction}; pub struct EventsEmitter { enigo: Enigo, - mouse: mouse_rs::Mouse, - left_mouse_held: bool, + session_restart_in_progress: bool, + + video_server_ch_sender: Sender, #[cfg(target_os = "linux")] uinput: mouse_keyboard_input::VirtualDevice, @@ -29,28 +29,45 @@ pub struct EventsEmitter { impl EventsEmitter { #[cfg(target_os = "linux")] - pub fn new() -> Self { + fn new(video_server_ch_sender: Sender) -> Self { use std::time::Duration; - let mouse = mouse_rs::Mouse::new(); // requires package install on linux (libxdo-dev) let uinput = mouse_keyboard_input::VirtualDevice::new(Duration::new(0.040 as u64, 0), 2000).unwrap(); let enigo = Enigo::new(&Settings::default()).unwrap(); Self { enigo, - mouse, uinput, + video_server_ch_sender, + session_restart_in_progress: false, left_mouse_held: false, } } + + fn reconnect_input_modules(&mut self) -> Result<(), Box> { + if cfg!(target_os = "linux") { + use std::time::Duration; + self.uinput = mouse_keyboard_input::VirtualDevice::new( + Duration::new(0.040 as u64, 0), 2000)?; + } + + self.enigo = Enigo::new(&Settings::default())?; + + self.session_restart_in_progress = false; + Ok(()) + } + #[cfg(not(target_os = "linux"))] - pub fn new() -> Self { - let mouse = mouse_rs::Mouse::new(); // requires package install on linux (libxdo-dev) + fn new() -> Self { let enigo = Enigo::new(&Settings::default()).unwrap(); - Self { mouse, enigo, left_mouse_held: false } + Self { + enigo, + session_restart_in_progress: false, + left_mouse_held: false + } } // sudo apt install libudev-dev libevdev-dev libhidapi-dev @@ -58,155 +75,197 @@ impl EventsEmitter { // sudo reboot #[cfg(target_os = "linux")] - pub fn scroll(&mut self, x: i32, y: i32) { + fn scroll(&mut self, x: i32, y: i32) { if x != 0 { - let _ = &self.uinput.scroll_x(-x * 3); + let _ = &self.uinput.scroll_x(-x * 2); } if y != 0 { - let _ = &self.uinput.scroll_y(-y * 3); + let _ = &self.uinput.scroll_y(-y * 2); } } #[cfg(not(target_os = "linux"))] - pub fn scroll(&self, _x: i32, _y: i32) {} - - pub fn input(&mut self, buf: &mut [u8], width: usize, height: usize) { - if click_requested(buf) { - let (x, y, right) = parse_click(buf, width, height); - - let _ = &self.mouse.move_to(x, y); - if right { - let _ = &self - .enigo - .button(enigo::Button::Right, enigo::Direction::Click); - } else { - self.left_mouse_held = !self.left_mouse_held; - let _ = &self - .enigo - .button(enigo::Button::Left, enigo::Direction::Click); - } - } - - if mouse_move_requested(buf) { - let (x, y, pressed) = parse_mouse_move(buf, width as f32, height as f32); - let _ = &self.mouse.move_to(x, y); - - if pressed && !self.left_mouse_held { - self.left_mouse_held = true; - let _ = &self - .enigo - .button(enigo::Button::Left, enigo::Direction::Press); - } - } - - if scroll_requested(&buf) { - let x_delta = i16::from_be_bytes(buf[14..16].try_into().unwrap()); - let y_delta = i16::from_be_bytes(buf[16..18].try_into().unwrap()); - - if cfg!(target_os = "linux") { - self.scroll(x_delta as i32, y_delta as i32); - } - } + fn scroll(&self, _x: i32, _y: i32) {} + fn handle_meta_keys(&mut self, buf: &[u8]) -> Result<(), InputError>{ if is_control_pressed(buf) { - self.enigo.key(enigo::Key::Control, Press).unwrap(); + self.enigo.key(enigo::Key::Control, Press)?; } else if is_control_released(buf) { - self.enigo.key(enigo::Key::Control, Release).unwrap(); + self.enigo.key(enigo::Key::Control, Release)?; } if is_shift_pressed(buf) { - self.enigo.key(enigo::Key::Shift, Press).unwrap(); + self.enigo.key(enigo::Key::Shift, Press)?; } else if is_shift_released(buf) { - self.enigo.key(enigo::Key::Shift, Release).unwrap(); + self.enigo.key(enigo::Key::Shift, Release)?; } if is_alt_pressed(buf) { - self.enigo.key(enigo::Key::Alt, Press).unwrap(); + self.enigo.key(enigo::Key::Alt, Press)?; } else if is_alt_released(buf) { - self.enigo.key(enigo::Key::Alt, Release).unwrap(); + self.enigo.key(enigo::Key::Alt, Release)?; } if is_meta_pressed(buf) { - self.enigo.key(enigo::Key::Meta, Press).unwrap(); + self.enigo.key(enigo::Key::Meta, Press)?; } else if is_meta_released(buf) { - self.enigo.key(enigo::Key::Meta, Release).unwrap(); + self.enigo.key(enigo::Key::Meta, Release)?; } + Ok(()) + } + + fn handle_pressed_key(&mut self, buf: &[u8]) -> Result<(), InputError>{ match Key::from(buf[8]) { Key::None => {} Key::Backspace => { - self.enigo.key(enigo::Key::Backspace, Press).unwrap(); + self.enigo.key(enigo::Key::Backspace, Press)?; } Key::DownArrow => { - self.enigo.key(enigo::Key::DownArrow, Press).unwrap(); + self.enigo.key(enigo::Key::DownArrow, Press)?; } Key::UpArrow => { - self.enigo.key(enigo::Key::UpArrow, Press).unwrap(); + self.enigo.key(enigo::Key::UpArrow, Press)?; } Key::LeftArrow => { - self.enigo.key(enigo::Key::LeftArrow, Press).unwrap(); + self.enigo.key(enigo::Key::LeftArrow, Press)?; } Key::RightArrow => { - self.enigo.key(enigo::Key::RightArrow, Press).unwrap(); + self.enigo.key(enigo::Key::RightArrow, Press)?; } Key::Space => { self.enigo - .key(enigo::Key::Space, enigo::Direction::Press) - .unwrap(); + .key(enigo::Key::Space, enigo::Direction::Press)?; } Key::Tab => { self.enigo - .key(enigo::Key::Tab, enigo::Direction::Press) - .unwrap(); + .key(enigo::Key::Tab, enigo::Direction::Press)?; } Key::Return => { self.enigo - .key(enigo::Key::Return, enigo::Direction::Click) - .unwrap(); + .key(enigo::Key::Return, enigo::Direction::Click)?; } Key::Unicode => { self.enigo - .key(enigo::Key::Unicode((buf[8]) as char), Press) - .unwrap(); + .key(enigo::Key::Unicode(buf[8] as char), Press)? } } + Ok(()) + } + + fn handle_released_key(&mut self, buf: &[u8]) -> Result<(), InputError> { match Key::from(buf[9]) { Key::None => {} Key::Backspace => { - self.enigo.key(enigo::Key::Backspace, Release).unwrap(); + self.enigo.key(enigo::Key::Backspace, Release)?; } Key::Space => { self.enigo - .key(enigo::Key::Space, enigo::Direction::Release) - .unwrap(); + .key(enigo::Key::Space, enigo::Direction::Release)?; } Key::DownArrow => { - self.enigo.key(enigo::Key::DownArrow, Release).unwrap(); + self.enigo.key(enigo::Key::DownArrow, Release)?; } Key::UpArrow => { - self.enigo.key(enigo::Key::UpArrow, Release).unwrap(); + self.enigo.key(enigo::Key::UpArrow, Release)?; } Key::LeftArrow => { - self.enigo.key(enigo::Key::LeftArrow, Release).unwrap(); + self.enigo.key(enigo::Key::LeftArrow, Release)?; } Key::RightArrow => { - self.enigo.key(enigo::Key::RightArrow, Release).unwrap(); + self.enigo.key(enigo::Key::RightArrow, Release)?; } Key::Tab => { self.enigo - .key(enigo::Key::Tab, enigo::Direction::Release) - .unwrap(); + .key(enigo::Key::Tab, enigo::Direction::Release)?; } Key::Return => {} Key::Unicode => { self.enigo - .key(enigo::Key::Unicode((buf[9]) as char), Release) - .unwrap(); + .key(enigo::Key::Unicode((buf[9]) as char), Release)?; } } + + Ok(()) } + + fn input(&mut self, buf: &mut [u8], width: usize, height: usize) { + // TODO: Scroll only works on linux + + if scroll_requested(&buf) { + let x_delta = i16::from_be_bytes(buf[14..16].try_into().unwrap()); + let y_delta = i16::from_be_bytes(buf[16..18].try_into().unwrap()); + + if cfg!(target_os = "linux") { + self.scroll(x_delta as i32, y_delta as i32); + } + } + + if click_requested(buf) { + let (x, y, right) = parse_click(buf, width, height); + + match self.enigo.move_mouse(x, y, enigo::Coordinate::Abs) { + Ok(_) => { + if right { + let _ = &self + .enigo + .button(enigo::Button::Right, enigo::Direction::Click); + } else { + self.left_mouse_held = !self.left_mouse_held; + let _ = &self + .enigo + .button(enigo::Button::Left, enigo::Direction::Click); + } + } + Err(e) => { + debug!("Error moving mouse for click: {}", e); + + if !self.session_restart_in_progress { + debug!("Session Restart Requested"); + let _ = self.video_server_ch_sender.send(VideoServerAction::RestartSession); + self.session_restart_in_progress = true; + } + } + } + } + + if mouse_move_requested(buf) { + let (x, y, pressed) = parse_mouse_move(buf, width as f32, height as f32); + + if let Err(e) = self.enigo.move_mouse(x as i32, y as i32, enigo::Coordinate::Abs) { + debug!("Error moving mouse: {}", e); + if !self.session_restart_in_progress { + debug!("Session Restart Requested"); + let _ = self.video_server_ch_sender.send(VideoServerAction::RestartSession); + self.session_restart_in_progress = true; + } + } + + if pressed && !self.left_mouse_held { + self.left_mouse_held = true; + let _ = &self + .enigo + .button(enigo::Button::Left, enigo::Direction::Press); + } + } + + if let Err(e) = self.handle_meta_keys(&buf) { + debug!("Error handling meta keys: {}", e); + } + + if let Err(e) = self.handle_pressed_key(&buf) { + debug!("Error handling pressed key: {}", e); + } + + if let Err(e) = self.handle_released_key(&buf) { + debug!("Error handling released key: {}", e); + } + } +} +pub enum EventsThreadAction { + ReconnectInputModules } pub struct EventsThread { @@ -223,7 +282,7 @@ impl EventsThread { video_server_ch_sender: Sender, ) -> Self { Self { - emitter: EventsEmitter::new(), + emitter: EventsEmitter::new(video_server_ch_sender.clone()), conn, headers, video_server_ch_sender, @@ -283,8 +342,6 @@ impl EventsThread { meta.height.try_into().unwrap(), ); - // TODO: Don't refresh encoder if the dimensions are the same - self.video_server_ch_sender .send(VideoServerAction::ConfigUpdate) .unwrap(); @@ -315,12 +372,30 @@ impl EventsThread { } } - fn start_loop(&mut self) { + fn start_loop(&mut self, event_ch_receiver: Receiver) { loop { let mut buf = [0u8; MTU]; - let (size, src) = self.conn.recv_from(&mut buf).unwrap(); - self.handle_event(&mut buf, src, size); + // TODO: Look into using try_recv_realtime, it could have some adverse effects + // TODO: Currently used for the belief that it is faster than `try_recv` + + while let Ok(action) = event_ch_receiver.try_recv_realtime() { + match action { + Some(EventsThreadAction::ReconnectInputModules) => { + if let Ok(()) = self.emitter.reconnect_input_modules() { + debug!("Reconnected input modules"); + } else { + debug!("Failed to reconnect input modules"); + } + self.emitter.session_restart_in_progress = false; + } + None => { break; } + } + } + + if let Ok((size, src)) = self.conn.recv_from(&mut buf) { + self.handle_event(&mut buf, src, size); + } } } @@ -328,12 +403,15 @@ impl EventsThread { conn: &Connection, headers: Vec, video_server_ch_sender: Sender, - ) { + event_ch_receiver: Receiver, + ) -> JoinHandle<()> { let conn = conn.clone(); - let _ = thread::spawn(move || { + let handle = thread::spawn(move || { let mut events = EventsThread::new(conn, headers, video_server_ch_sender); - events.start_loop(); + events.start_loop(event_ch_receiver); }); + + handle } } diff --git a/mrial_server/src/video/mod.rs b/mrial_server/src/video/mod.rs index ea39778..baa6189 100644 --- a/mrial_server/src/video/mod.rs +++ b/mrial_server/src/video/mod.rs @@ -1,22 +1,24 @@ pub mod display; pub mod yuv; +pub mod session; use deploy::PacketDeployer; use display::DisplayMeta; use futures::{executor::ThreadPool, future::RemoteHandle, task::SpawnExt}; -use kanal::unbounded; +use kanal::{unbounded, Receiver, Sender}; use log::debug; use mrial_proto::*; use scrap::{Capturer, Display}; +use session::{SessionSettingThread, Setting}; use std::{ - collections::VecDeque, env, fs::File, io::{ErrorKind::WouldBlock, Write}, process::Command, sync::RwLockReadGuard, thread, time::{Duration, Instant} + collections::VecDeque, fs::File, io::{ErrorKind::WouldBlock, Write}, sync::RwLockReadGuard, thread, time::{Duration, Instant} }; use x264::{Encoder, Param, Picture}; use yuv::YUVBuffer; use crate::{ conn::{Connection, ServerMetaData}, - events::EventsThread, + events::{EventsThread, EventsThreadAction}, }; use self::yuv::EColorSpace; @@ -28,13 +30,7 @@ pub enum VideoServerAction { NewUserSession, RestartStream, SymKey, -} - -#[derive(PartialEq)] -pub enum Setting { - Unknown, - PreLogin, - PostLogin + RestartSession, } pub struct VideoServerThread { @@ -49,45 +45,11 @@ pub struct VideoServerThread { deployer: PacketDeployer, conn: Connection, setting: Setting, -} - -fn get_x11_authenicated_client() -> Option { - let gui_users_output = Command::new("sh") - .arg("-c") - .arg("who | grep tty7") - .output() - .unwrap(); + setting_thread: Option>, - if gui_users_output.stdout.is_empty() || !gui_users_output.status.success() { - return None; - } - - let output_str = String::from_utf8(gui_users_output.stdout).unwrap(); - if let Some(user) = output_str.split_whitespace().next() { - return Some(user.to_string()); - } - - None -} - -struct SessionSettingThread { -} - -impl SessionSettingThread { - pub fn run(video_server_ch_sender: kanal::Sender) { - let _ = thread::spawn(move || { - loop { - if get_x11_authenicated_client().is_some() { - debug!("User has logged in"); - video_server_ch_sender.send(VideoServerAction::NewUserSession).unwrap(); - break; - } - debug!("Waiting for user to login"); - - thread::sleep(Duration::from_secs(1)); - } - }); - } + events_sender: Sender, + events_receiver: Receiver, + events_thread: Option>, } impl VideoServerThread { @@ -95,7 +57,7 @@ impl VideoServerThread { let mut setting = Setting::Unknown; if cfg!(target_os = "linux") { - setting = VideoServerThread::config_xenv()?; + setting = session::config_xenv()?; } let display: Display = Display::primary()?; @@ -112,7 +74,14 @@ impl VideoServerThread { let encoder = x264::Encoder::open(&mut par)?; let pic = Picture::from_param(&par)?; + let (events_sender, events_receiver) = unbounded::(); + Ok(Self { + events_receiver, + events_sender, + events_thread: None, + + setting_thread: None, pool, yuv_handles, row_len, @@ -127,58 +96,6 @@ impl VideoServerThread { }) } - /* - * Configures the X environment for the server by setting - * correct display and Xauthority variables. - * - * Additionally, it sets the XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS - * for pipewire connection from root. - * - */ - - // TODO: Make DISPLAY variable dynamic AND - // TODO: not assume the display manager is lightdm - - #[cfg(target_os = "linux")] - fn config_xenv() -> Result> { - env::set_var("DISPLAY", ":0"); - - if let Some(username) = get_x11_authenicated_client() { - /* - * Environment variables needed to connect to - * user graphical user session from root - */ - let xauthority_path = format!("/home/{}/.Xauthority", username); - debug!("Xauthority User Path: {}", xauthority_path); - env::set_var("XAUTHORITY", xauthority_path); - - /* - * Environment variables needed for pipewire connection from root. - */ - let user_id_cmd = format!("id -u {}", username); - let user_id_output = Command::new("sh") - .arg("-c") - .arg(user_id_cmd) - .output() - .unwrap(); - - let user_id = String::from_utf8(user_id_output.stdout).unwrap(); - let xdg_runtime_dir = format!("/run/user/{}", user_id.trim()); - let dbus_session_bus_address = format!("unix:path={}/bus", xdg_runtime_dir); - - debug!("XDG_RUNTIME_DIR: {}", &xdg_runtime_dir); - debug!("DBUS_SESSION_BUS_ADDRESS: {}", &dbus_session_bus_address); - - env::set_var("XDG_RUNTIME_DIR", xdg_runtime_dir); - env::set_var("DBUS_SESSION_BUS_ADDRESS", dbus_session_bus_address); - - return Ok(Setting::PostLogin); - } - - env::set_var("XAUTHORITY", "/var/lib/lightdm/.Xauthority"); - return Ok(Setting::PreLogin); - } - #[inline] #[allow(dead_code)] fn write_stream(&mut self, bitstream: &[u8]) { @@ -206,9 +123,40 @@ impl VideoServerThread { } fn drop_capturer(&mut self) { - let capturer = self.capturer.take().unwrap(); - debug!("Dropping Capturer"); - drop(capturer); + if let Some(capturer) = self.capturer.take() { + debug!("Dropping Capturer"); + drop(capturer); + } + } + + fn restart_stream(&mut self) -> Result<(), Box> { + let display = Display::primary()?; + + let capturer: Capturer = Capturer::new(display)?; + + self.row_len = 4 * capturer.width() * capturer.height(); + self.conn + .set_dimensions(capturer.width(), capturer.height()); + self.par = VideoServerThread::get_parameters(self.conn.get_meta()); + self.encoder = x264::Encoder::open(&mut self.par)?; + + if self.deployer.has_sym_key() { + let headers = self.encoder.get_headers()?; + let header_bytes = headers.as_bytes(); + self.deployer.prepare( + &header_bytes, + Box::new(|subpacket| { + self.conn.broadcast(&subpacket); + }), + ); + } + + self.pic = Picture::from_param(&self.par)?; + + self.yuv_handles.clear(); + self.capturer = Some(capturer); + + Ok(()) } fn handle_server_action( @@ -217,22 +165,24 @@ impl VideoServerThread { video_server_ch_sender: &kanal::Sender ) { match server_action { - Some(VideoServerAction::NewUserSession) => { - match VideoServerThread::config_xenv() { + Some(VideoServerAction::RestartSession) => { + match session::config_xenv() { Ok(Setting::PostLogin) => { self.setting = Setting::PostLogin; + } + Ok(Setting::PreLogin) => { + self.setting = Setting::PreLogin; + } + _ => {} + } - // TODO: This does not work, maybe this needs to be done after more time, - // TODO: because the resolution does not change, or maybe it just doesn't know the - // TODO: correct resolution - if let Ok((width, height)) = DisplayMeta::get_current_resolution() { - debug!("Post-Login Resolution: {}x{}", width, height); - - if let Err(e) = DisplayMeta::update_display_resolution(width, height) { - debug!("Error syncing display resolution after login: {}", e.to_string()); - } - } - + video_server_ch_sender.send(VideoServerAction::RestartStream).unwrap(); + self.events_sender.send(EventsThreadAction::ReconnectInputModules).unwrap(); + } + Some(VideoServerAction::NewUserSession) => { + match session::config_xenv() { + Ok(Setting::PostLogin) => { + self.setting = Setting::PostLogin; video_server_ch_sender.send(VideoServerAction::RestartStream).unwrap(); } _ => {} @@ -248,52 +198,20 @@ impl VideoServerThread { } Some(VideoServerAction::RestartStream) => { self.drop_capturer(); - - let display = Display::primary().unwrap(); - self.capturer = Some(Capturer::new(display).unwrap()); - - let capturer = self.capturer.as_ref().unwrap(); - - self.row_len = 4 * capturer.width() * capturer.height(); - - self.conn - .set_dimensions(capturer.width(), capturer.height()); - - self.par = VideoServerThread::get_parameters(self.conn.get_meta()); - self.encoder = x264::Encoder::open(&mut self.par).unwrap(); - - if self.deployer.has_sym_key() { - let headers = self.encoder.get_headers().unwrap(); - let header_bytes = headers.as_bytes(); - self.deployer.prepare( - &header_bytes, - Box::new(|subpacket| { - self.conn.broadcast(&subpacket); - }), - ); + match self.restart_stream() { + Ok(_) => { + debug!("Restarted Stream Successfully"); + } + Err(e) => { + debug!("Error Restarting Stream: {}", e); + video_server_ch_sender.send(VideoServerAction::RestartStream).unwrap(); + } } - - self.pic = Picture::from_param(&self.par).unwrap(); - - self.yuv_handles.clear(); } Some(VideoServerAction::ConfigUpdate) => { let requested_width = self.conn.get_meta().width; let requested_height = self.conn.get_meta().height; - let capturer = match &self.capturer { - Some(capturer) => capturer, - None => { - return; - } - }; - - if requested_width == capturer.width() as usize - && requested_height == capturer.height() as usize - { - return; - } - if let Err(e) = DisplayMeta::update_display_resolution(requested_width, requested_height) { debug!("Error updating display resolution: {}", e); } @@ -306,6 +224,42 @@ impl VideoServerThread { } } + fn start_session_thread(&mut self, ch_sender: Sender) -> bool { + let has_setting_thread = match &self.setting_thread { + Some(handle) => !handle.is_finished(), + None => false, + }; + + if has_setting_thread { return false; } + + self.setting_thread = Some(SessionSettingThread::run( + ch_sender, + self.setting + )); + true + } + + fn start_events_thread( + &mut self, + headers: Vec, + ch_sender: Sender) -> bool { + let has_events_thread = match &self.events_thread { + Some(handle) => !handle.is_finished(), + None => false, + }; + + if has_events_thread { return false; } + + self.events_thread = Some(EventsThread::run( + &self.conn, + headers, + ch_sender, + self.events_receiver.clone() + )); + + true + } + #[inline] pub async fn run(&mut self) { let (ch_sender, ch_receiver) = unbounded::(); @@ -315,11 +269,9 @@ impl VideoServerThread { // Send update to client to update headers let headers = self.encoder.get_headers().unwrap(); - EventsThread::run(&self.conn, headers.as_bytes().to_vec(), ch_sender.clone()); - - if self.setting == Setting::PreLogin { - SessionSettingThread::run(ch_sender.clone()); - } + + self.start_events_thread(headers.as_bytes().to_vec(), ch_sender.clone()); + self.start_session_thread(ch_sender.clone()); loop { while ch_receiver.len() > 0 { @@ -411,7 +363,8 @@ impl VideoServerThread { } } Err(ref e) if e.kind() == WouldBlock => {} - Err(_) => { + Err(e) => { + println!("Error: {}", e); debug!("Error Capturing Frame") } } diff --git a/mrial_server/src/video/session.rs b/mrial_server/src/video/session.rs new file mode 100644 index 0000000..80403dd --- /dev/null +++ b/mrial_server/src/video/session.rs @@ -0,0 +1,168 @@ +use std::{process::Command, thread, time::Duration}; + +use kanal::{SendError, Sender}; +use log::{debug, error, trace}; + +use super::VideoServerAction; + +#[derive(PartialEq, Clone, Copy)] +pub enum Setting { + Unknown, + PreLogin, + PostLogin +} + +/* + * Configures the X environment for the server by setting + * correct display and Xauthority variables. + * + * Additionally, it sets the XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS + * for pipewire connection from root. + */ + +// TODO: Make DISPLAY variable dynamic AND +// TODO: don't assume the display manager is lightdm + +#[cfg(target_os = "linux")] +pub fn config_xenv() -> Result> { + use std::env; + + env::set_var("DISPLAY", ":0"); + + if let Ok(Some(username)) = get_x11_authenicated_client() { + /* + * Environment variables needed to connect to + * user graphical user session from root + */ + let xauthority_path = format!("/home/{}/.Xauthority", username); + debug!("Xauthority User Path: {}", xauthority_path); + env::set_var("XAUTHORITY", xauthority_path); + + /* + * Environment variables needed for pipewire connection from root. + */ + let user_id_cmd = format!("id -u {}", username); + let user_id_output = Command::new("sh") + .arg("-c") + .arg(user_id_cmd) + .output()?; + + let user_id = String::from_utf8(user_id_output.stdout)?; + let xdg_runtime_dir = format!("/run/user/{}", user_id.trim()); + let dbus_session_bus_address = format!("unix:path={}/bus", xdg_runtime_dir); + + debug!("XDG_RUNTIME_DIR: {}", &xdg_runtime_dir); + debug!("DBUS_SESSION_BUS_ADDRESS: {}", &dbus_session_bus_address); + + env::set_var("XDG_RUNTIME_DIR", xdg_runtime_dir); + env::set_var("DBUS_SESSION_BUS_ADDRESS", dbus_session_bus_address); + + return Ok(Setting::PostLogin); + } + + debug!("No user logged in to graphical session"); + env::set_var("XAUTHORITY", "/var/lib/lightdm/.Xauthority"); + return Ok(Setting::PreLogin); +} + +#[cfg(target_os = "linux")] +fn get_x11_authenicated_client() -> Result, Box> { + let gui_users_output = Command::new("sh") + .arg("-c") + .arg("who | grep tty7") + .output()?; + + if gui_users_output.stdout.is_empty() || !gui_users_output.status.success() { + return Ok(None); + } + + let output_str = String::from_utf8(gui_users_output.stdout)?; + if let Some(user) = output_str.split_whitespace().next() { + return Ok(Some(user.to_string())); + } + + Ok(None) +} + +const SESSION_CHECK_INTERVAL: u64 = 1; + +pub struct SessionSettingThread { + setting: Setting, + video_server_ch_sender: Sender +} + +impl SessionSettingThread { + #[cfg(target_os = "linux")] + fn check_x11_user_logged_in(&mut self) -> Result<(), SendError> { + match get_x11_authenicated_client() { + Ok(Some(_)) => { + debug!("User has logged in"); + + self.setting = Setting::PostLogin; + self.video_server_ch_sender.send(VideoServerAction::NewUserSession)?; + } + Err(e) => { + error!("Error checking for X11 authenticated client: {:?}", e); + } + _ => {} + } + trace!("Waiting for user to login"); + + Ok(()) + } + + #[cfg(target_os = "linux")] + fn check_x11_user_logged_out(&mut self) -> Result<(), SendError> { + match get_x11_authenicated_client() { + Ok(None) => { + debug!("User has logged out"); + + self.setting = Setting::PreLogin; + self.video_server_ch_sender.send(VideoServerAction::RestartSession)?; + } + Err(e) => { + error!("Error checking for X11 authenticated client: {:?}", e); + } + _ => {} + } + trace!("Waiting for user to logout"); + + Ok(()) + } + + #[cfg(target_os = "linux")] + fn x11_session_status_loop(&mut self) -> Result<(), SendError> { + loop { + match self.setting { + Setting::PreLogin => { + self.check_x11_user_logged_in()?; + } + Setting::PostLogin => { + self.check_x11_user_logged_out()?; + } + Setting::Unknown => { + + } + } + + thread::sleep(Duration::from_secs(SESSION_CHECK_INTERVAL)); + } + } + + pub fn run( + video_server_ch_sender: Sender, + setting: Setting) -> thread::JoinHandle<()> { + return thread::spawn(move || { + let mut session_setting_thread = SessionSettingThread { + video_server_ch_sender, + setting, + }; + + if cfg!(target_os = "linux") { + if let Err(e) = session_setting_thread.x11_session_status_loop() { + error!("X11 session status loop crashed: {:?}", e); + } + } + }); + } +}