mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 20:09:59 +03:00
Support event consumer on KDE! (portal backend) (#31)
* Support event consumer on KDE! (portal backend) Support for KDE event emulation using the remote-desktop xdg-desktop-portal * fix scrolling (TODO: smooth / kinetic scrolling) * windows: fix compilation errors * Update README.md
This commit is contained in:
committed by
GitHub
parent
4cdc5ea49c
commit
be0fe9f2d9
550
Cargo.lock
generated
550
Cargo.lock
generated
@@ -32,6 +32,109 @@ version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "ashpd"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3affe251686bd936a0afb74b9693e8bf2f193d51da1b9a45d3f1303a9bd2cc7"
|
||||
dependencies = [
|
||||
"enumflags2",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"once_cell",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
"tokio",
|
||||
"url",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-lite",
|
||||
"log",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix 0.37.24",
|
||||
"slab",
|
||||
"socket2 0.4.9",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"blocking",
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"rustix 0.37.24",
|
||||
"signal-hook",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.73"
|
||||
@@ -43,6 +146,12 @@ dependencies = [
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@@ -76,6 +185,37 @@ version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-lock",
|
||||
"async-task",
|
||||
"fastrand 2.0.0",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"piper",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.5.0"
|
||||
@@ -132,12 +272,70 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.2"
|
||||
@@ -165,6 +363,27 @@ dependencies = [
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939"
|
||||
dependencies = [
|
||||
"enumflags2_derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2_derive"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.0"
|
||||
@@ -205,6 +424,21 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.0"
|
||||
@@ -262,6 +496,21 @@ version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
||||
dependencies = [
|
||||
"fastrand 1.9.0",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"memchr",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.28"
|
||||
@@ -273,6 +522,12 @@ dependencies = [
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.28"
|
||||
@@ -287,6 +542,7 @@ checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
@@ -351,6 +607,16 @@ dependencies = [
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
@@ -590,6 +856,12 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.3.1"
|
||||
@@ -627,6 +899,15 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
@@ -644,7 +925,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"socket2 0.5.4",
|
||||
"widestring",
|
||||
"windows-sys",
|
||||
"winreg",
|
||||
@@ -663,7 +944,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"rustix 0.38.13",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -678,6 +959,8 @@ name = "lan-mouse"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ashpd",
|
||||
"async-trait",
|
||||
"env_logger",
|
||||
"glib-build-tools",
|
||||
"gtk4",
|
||||
@@ -754,6 +1037,12 @@ version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.7"
|
||||
@@ -882,6 +1171,16 @@ version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-stream"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.18.0"
|
||||
@@ -907,6 +1206,12 @@ dependencies = [
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
@@ -948,12 +1253,39 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "piper"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"fastrand 2.0.0",
|
||||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"libc",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1120,6 +1452,20 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.8",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.13"
|
||||
@@ -1129,7 +1475,7 @@ dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.4.7",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -1188,6 +1534,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.3"
|
||||
@@ -1197,6 +1554,36 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
@@ -1212,6 +1599,16 @@ version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.4"
|
||||
@@ -1222,6 +1619,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@@ -1270,9 +1673,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"fastrand 2.0.0",
|
||||
"redox_syscall",
|
||||
"rustix",
|
||||
"rustix 0.38.13",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -1332,8 +1735,10 @@ dependencies = [
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"signal-hook-registry",
|
||||
"socket2 0.5.4",
|
||||
"tokio-macros",
|
||||
"tracing",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
@@ -1460,6 +1865,22 @@ dependencies = [
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "uds_windows"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d"
|
||||
dependencies = [
|
||||
"tempfile",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
@@ -1490,6 +1911,7 @@ dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1504,6 +1926,12 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -1741,3 +2169,113 @@ dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xdg-home"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "3.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-process",
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"byteorder",
|
||||
"derivative",
|
||||
"enumflags2",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"nix",
|
||||
"once_cell",
|
||||
"ordered-stream",
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
"sha1",
|
||||
"static_assertions",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"uds_windows",
|
||||
"winapi",
|
||||
"xdg-home",
|
||||
"zbus_macros",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "3.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 1.0.109",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_names"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "3.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"enumflags2",
|
||||
"libc",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"url",
|
||||
"zvariant_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "3.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_utils"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@@ -23,7 +23,8 @@ log = "0.4.20"
|
||||
env_logger = "0.10.0"
|
||||
libc = "0.2.148"
|
||||
serde_json = "1.0.107"
|
||||
tokio = {version = "1.32.0", features = ["io-util", "macros", "net", "rt", "sync" ] }
|
||||
tokio = {version = "1.32.0", features = ["io-util", "macros", "net", "rt", "sync", "signal"] }
|
||||
async-trait = "0.1.73"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
wayland-client = { version="0.30.2", optional = true }
|
||||
@@ -34,6 +35,7 @@ wayland-protocols-plasma = { version="0.1.0", features=["client"], optional = tr
|
||||
x11 = { version = "2.21.0", features = ["xlib", "xtest"], optional = true }
|
||||
gtk = { package = "gtk4", version = "0.7.2", features = ["v4_6"], optional = true }
|
||||
adw = { package = "libadwaita", version = "0.5.2", features = ["v1_1"], optional = true }
|
||||
ashpd = { version = "0.6.2", default-features = false, features = ["tokio"], optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3.9", features = ["winuser"] }
|
||||
@@ -56,6 +58,6 @@ wayland = [
|
||||
"dep:wayland-protocols-misc",
|
||||
"dep:wayland-protocols-plasma" ]
|
||||
x11 = [ "dep:x11" ]
|
||||
xdg_desktop_portal = []
|
||||
xdg_desktop_portal = ["dep:ashpd"]
|
||||
libei = []
|
||||
gtk = ["dep:gtk", "dep:adw"]
|
||||
|
||||
205
README.md
205
README.md
@@ -1,54 +1,29 @@
|
||||
# Lan Mouse
|
||||
- _Now with a gtk frontend_
|
||||
|
||||

|
||||
|
||||
<img src="https://github.com/ferdinandschober/lan-mouse/assets/40996949/ccb33815-4357-4c8d-a5d2-8897ab626a08" width=75%>
|
||||
|
||||
Goal of this project is to be an open-source replacement for proprietary tools like [Synergy](https://symless.com/synergy), [Share Mouse](https://www.sharemouse.com/de/).
|
||||
|
||||
Focus lies on performance and a clean, manageable implementation that can easily be expanded to support additional backends like e.g. Android, iOS, ... .
|
||||
|
||||
Of course ***blazingly fast™*** and stable, because it's written in rust.
|
||||
***blazingly fast™*** and ***stable™***, because it's written in rust.
|
||||
|
||||
For an alternative (with slightly different goals) you may check out [Input Leap](https://github.com/input-leap).
|
||||
|
||||
_Now with a gtk frontend_
|
||||
## OS Support
|
||||
|
||||
## Configuration
|
||||
Configuration is done through the file `config.toml`,
|
||||
which must be located in the current working directory when
|
||||
executing lan-mouse.
|
||||
The following table shows support for Event receiving and event Emitting
|
||||
on different operating systems:
|
||||
|
||||
### Example config
|
||||
A config file could look like this:
|
||||
|
||||
```toml
|
||||
# example configuration
|
||||
|
||||
# optional port (defaults to 4242)
|
||||
port = 4242
|
||||
# # optional frontend -> defaults to gtk if available
|
||||
# # possible values are "cli" and "gtk"
|
||||
# frontend = "gtk"
|
||||
|
||||
# define a client on the right side with host name "iridium"
|
||||
[right]
|
||||
# hostname
|
||||
host_name = "iridium"
|
||||
# optional list of (known) ip addresses
|
||||
ips = ["192.168.178.156"]
|
||||
|
||||
# define a client on the left side with IP address 192.168.178.189
|
||||
[left]
|
||||
# The hostname is optional: When no hostname is specified,
|
||||
# at least one ip address needs to be specified.
|
||||
host_name = "thorium"
|
||||
# ips for ethernet and wifi
|
||||
ips = ["192.168.178.189", "192.168.178.172"]
|
||||
# optional port
|
||||
port = 4242
|
||||
```
|
||||
|
||||
Where `left` can be either `left`, `right`, `top` or `bottom`.
|
||||
| Backend | Event Receiving | Event Emitting |
|
||||
|---------------------------|--------------------------|--------------------------------------|
|
||||
| Wayland (wlroots) | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Wayland (KDE) | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Wayland (Gnome) | TODO (libei support) | TODO (wlr-layer-shell not supported) |
|
||||
| X11 | (WIP) | TODO |
|
||||
| Windows | (:heavy_check_mark:) | TODO |
|
||||
| MacOS | TODO (I dont own a Mac) | TODO (I dont own a Mac) |
|
||||
|
||||
|
||||
## Build and Run
|
||||
@@ -81,79 +56,42 @@ an executable with just support for wayland:
|
||||
cargo build --no-default-features --features wayland
|
||||
```
|
||||
|
||||
## OS Support
|
||||
## Configuration
|
||||
To automatically load clients on startup, the file `config.toml` is parsed.
|
||||
(must be in the directory where lan-mouse is executed).
|
||||
|
||||
The following table shows support for Event receiving and event Emitting
|
||||
on different operating systems:
|
||||
### Example config
|
||||
|
||||
| Backend | Event Receiving | Event Emitting |
|
||||
|---------------------------|--------------------------|--------------------------------------|
|
||||
| Wayland (wlroots) | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| Wayland (KDE) | WIP | :heavy_check_mark: |
|
||||
| Wayland (Gnome) | TODO (libei support) | TODO (wlr-layer-shell not supported) |
|
||||
| X11 | WIP | TODO |
|
||||
| Windows | needs improvements | TODO |
|
||||
| MacOS | TODO (I dont own a Mac) | TODO (I dont own a Mac) |
|
||||
```toml
|
||||
# example configuration
|
||||
|
||||
## Wayland compositor support
|
||||
### Input Emulation (for receiving events)
|
||||
On wayland input-emulation is in an early/unstable state as of writing this.
|
||||
# optional port (defaults to 4242)
|
||||
port = 4242
|
||||
# # optional frontend -> defaults to gtk if available
|
||||
# # possible values are "cli" and "gtk"
|
||||
# frontend = "gtk"
|
||||
|
||||
Different compositors have different ways of enabling input emulation:
|
||||
# define a client on the right side with host name "iridium"
|
||||
[right]
|
||||
# hostname
|
||||
host_name = "iridium"
|
||||
# optional list of (known) ip addresses
|
||||
ips = ["192.168.178.156"]
|
||||
|
||||
Most wlroots-based compositors like Hyprland and Sway support the following
|
||||
unstable wayland protocols for keyboard and mouse emulation:
|
||||
- [virtual-keyboard-unstable-v1](https://wayland.app/protocols/virtual-keyboard-unstable-v1)
|
||||
- [wlr-virtual-pointer-unstable-v1](https://wayland.app/protocols/wlr-virtual-pointer-unstable-v1) are used to emulate input on wlroots compositors
|
||||
# define a client on the left side with IP address 192.168.178.189
|
||||
[left]
|
||||
# The hostname is optional: When no hostname is specified,
|
||||
# at least one ip address needs to be specified.
|
||||
host_name = "thorium"
|
||||
# ips for ethernet and wifi
|
||||
ips = ["192.168.178.189", "192.168.178.172"]
|
||||
# optional port
|
||||
port = 4242
|
||||
```
|
||||
|
||||
KDE also has a protocol for input emulation ([kde-fake-input](https://wayland.app/protocols/kde-fake-input)), it is however not exposed to
|
||||
third party apps, so the recommended way of enabling input emulation in KDE is the
|
||||
[freedesktop remote-desktop-portal](https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.RemoteDesktop).
|
||||
Where `left` can be either `left`, `right`, `top` or `bottom`.
|
||||
|
||||
Gnome uses [libei](https://gitlab.freedesktop.org/libinput/libei) for input emulation,
|
||||
which has the goal to become the general approach for emulating Input on wayland.
|
||||
|
||||
| Required Protocols (Event Receiving) | Sway | Kwin | Gnome |
|
||||
|----------------------------------------|--------------------|----------------------|----------------------|
|
||||
| wlr-virtual-pointer-unstable-v1 | :heavy_check_mark: | :x: | :x: |
|
||||
| virtual-keyboard-unstable-v1 | :heavy_check_mark: | :x: | :x: |
|
||||
| ~fake-input~ | :x: | ~:heavy_check_mark:~ | :x: |
|
||||
|
||||
### Input capture
|
||||
|
||||
To capture mouse and keyboard input, a few things are necessary:
|
||||
- Displaying an immovable surface at screen edges
|
||||
- Locking the mouse in place
|
||||
- (optionally but highly recommended) reading unaccelerated mouse input
|
||||
|
||||
| Required Protocols (Event Emitting) | Sway | Kwin | Gnome |
|
||||
|----------------------------------------|--------------------|----------------------|----------------------|
|
||||
| pointer-constraints-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| relative-pointer-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| keyboard-shortcuts-inhibit-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| wlr-layer-shell-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :x: |
|
||||
|
||||
The [zwlr\_virtual\_pointer\_manager\_v1](wlr-virtual-pointer-unstable-v1) is required
|
||||
to display surfaces on screen edges and used to display the immovable window on
|
||||
both wlroots based compositors and KDE.
|
||||
|
||||
Gnome unfortunately does not support this protocol
|
||||
and [likely won't ever support it](https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1141).
|
||||
|
||||
So there is currently no way of doing this in Wayland, aside from a custom Gnome-Shell
|
||||
extension, which is not a very elegant solution.
|
||||
|
||||
This is to be looked into in the future.
|
||||
|
||||
~In order for layershell surfaces to be able to lock the pointer using the pointer\_constraints protocol [this patch](https://github.com/swaywm/sway/pull/7178) needs to be applied to sway.~
|
||||
(this works natively on sway versions >= 1.8)
|
||||
|
||||
## Windows support
|
||||
Currently windows can receive mouse and keyboard events,
|
||||
event producing on windows is WIP.
|
||||
|
||||
|
||||
## TODOS
|
||||
## Roadmap
|
||||
- [x] Capture the actual mouse events on the server side via a wayland client and send them to the client
|
||||
- [x] Mouse grabbing
|
||||
- [x] Window with absolute position -> wlr\_layer\_shell
|
||||
@@ -219,3 +157,60 @@ would be a better choice for the future and could also help for WIFI connections
|
||||
Sending key and mouse event data over the local network might not be the biggest security concern but in any public network or business environment it's *QUITE* a problem to basically broadcast your keystrokes.
|
||||
- There should be an encryption layer below the application to enable a secure link.
|
||||
- The encryption keys could be generated by the graphical frontend.
|
||||
|
||||
|
||||
## Wayland support
|
||||
### Input Emulation (for receiving events)
|
||||
On wayland input-emulation is in an early/unstable state as of writing this.
|
||||
|
||||
For this reason a suitable backend is chosen based on the active desktop environment / compositor.
|
||||
|
||||
Different compositors have different ways of enabling input emulation:
|
||||
|
||||
#### Wlroots
|
||||
Most wlroots-based compositors like Hyprland and Sway support the following
|
||||
unstable wayland protocols for keyboard and mouse emulation:
|
||||
- [virtual-keyboard-unstable-v1](https://wayland.app/protocols/virtual-keyboard-unstable-v1)
|
||||
- [wlr-virtual-pointer-unstable-v1](https://wayland.app/protocols/wlr-virtual-pointer-unstable-v1)
|
||||
|
||||
#### KDE
|
||||
KDE also has a protocol for input emulation ([kde-fake-input](https://wayland.app/protocols/kde-fake-input)),
|
||||
it is however not exposed to third party applications.
|
||||
|
||||
The recommended way to emulate input on KDE is the
|
||||
[freedesktop remote-desktop-portal](https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.RemoteDesktop).
|
||||
|
||||
#### Gnome (TODO)
|
||||
Gnome uses [libei](https://gitlab.freedesktop.org/libinput/libei) for input emulation,
|
||||
which has the goal to become the general approach for emulating Input on wayland.
|
||||
|
||||
|
||||
### Input capture
|
||||
|
||||
To capture mouse and keyboard input, a few things are necessary:
|
||||
- Displaying an immovable surface at screen edges
|
||||
- Locking the mouse in place
|
||||
- (optionally but highly recommended) reading unaccelerated mouse input
|
||||
|
||||
| Required Protocols (Event Emitting) | Sway | Kwin | Gnome |
|
||||
|----------------------------------------|--------------------|----------------------|----------------------|
|
||||
| pointer-constraints-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| relative-pointer-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| keyboard-shortcuts-inhibit-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| wlr-layer-shell-unstable-v1 | :heavy_check_mark: | :heavy_check_mark: | :x: |
|
||||
|
||||
The [zwlr\_virtual\_pointer\_manager\_v1](wlr-virtual-pointer-unstable-v1) is required
|
||||
to display surfaces on screen edges and used to display the immovable window on
|
||||
both wlroots based compositors and KDE.
|
||||
|
||||
Gnome unfortunately does not support this protocol
|
||||
and [likely won't ever support it](https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1141).
|
||||
|
||||
So there is currently no way of doing this in Wayland, aside from a custom Gnome-Shell
|
||||
extension, which is not a very elegant solution.
|
||||
|
||||
This is to be looked into in the future.
|
||||
|
||||
~In order for layershell surfaces to be able to lock the pointer using the pointer\_constraints protocol [this patch](https://github.com/swaywm/sway/pull/7178) needs to be applied to sway.~
|
||||
(this works natively on sway versions >= 1.8)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::consumer::EventConsumer;
|
||||
use crate::consumer::SyncConsumer;
|
||||
|
||||
pub struct LibeiConsumer {}
|
||||
|
||||
@@ -6,7 +6,7 @@ impl LibeiConsumer {
|
||||
pub fn new() -> Self { Self { } }
|
||||
}
|
||||
|
||||
impl EventConsumer for LibeiConsumer {
|
||||
impl SyncConsumer for LibeiConsumer {
|
||||
fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) {
|
||||
log::error!("libei backend not yet implemented!");
|
||||
todo!()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{event::{KeyboardEvent, PointerEvent}, consumer::EventConsumer};
|
||||
use crate::{event::{KeyboardEvent, PointerEvent}, consumer::SyncConsumer};
|
||||
use winapi::{
|
||||
self,
|
||||
um::winuser::{INPUT, INPUT_MOUSE, LPINPUT, MOUSEEVENTF_MOVE, MOUSEINPUT,
|
||||
@@ -25,7 +25,7 @@ impl WindowsConsumer {
|
||||
pub fn new() -> Self { Self { } }
|
||||
}
|
||||
|
||||
impl EventConsumer for WindowsConsumer {
|
||||
impl SyncConsumer for WindowsConsumer {
|
||||
fn consume(&mut self, event: Event, _: ClientHandle) {
|
||||
match event {
|
||||
Event::Pointer(pointer_event) => match pointer_event {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use wayland_client::WEnum;
|
||||
use wayland_client::backend::WaylandError;
|
||||
use crate::client::{ClientHandle, ClientEvent};
|
||||
use crate::consumer::EventConsumer;
|
||||
use crate::consumer::SyncConsumer;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::os::fd::OwnedFd;
|
||||
@@ -140,7 +140,7 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventConsumer for WlrootsConsumer {
|
||||
impl SyncConsumer for WlrootsConsumer {
|
||||
fn consume(&mut self, event: Event, client_handle: ClientHandle) {
|
||||
if let Some(virtual_input) = self.state.input_for_client.get(&client_handle) {
|
||||
if self.last_flush_failed {
|
||||
|
||||
@@ -3,7 +3,7 @@ use x11::{xlib, xtest};
|
||||
|
||||
use crate::{
|
||||
client::ClientHandle,
|
||||
event::Event, consumer::EventConsumer,
|
||||
event::Event, consumer::SyncConsumer,
|
||||
};
|
||||
|
||||
pub struct X11Consumer {
|
||||
@@ -30,7 +30,7 @@ impl X11Consumer {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventConsumer for X11Consumer {
|
||||
impl SyncConsumer for X11Consumer {
|
||||
fn consume(&mut self, event: Event, _: ClientHandle) {
|
||||
match event {
|
||||
Event::Pointer(pointer_event) => match pointer_event {
|
||||
|
||||
@@ -1,15 +1,91 @@
|
||||
use crate::consumer::EventConsumer;
|
||||
use async_trait::async_trait;
|
||||
use anyhow::Result;
|
||||
use ashpd::{desktop::{remote_desktop::{RemoteDesktop, DeviceType, KeyState, Axis}, Session}, WindowIdentifier};
|
||||
|
||||
pub struct DesktopPortalConsumer {}
|
||||
use crate::consumer::AsyncConsumer;
|
||||
|
||||
impl DesktopPortalConsumer {
|
||||
pub fn new() -> Self { Self { } }
|
||||
pub struct DesktopPortalConsumer<'a> {
|
||||
proxy: RemoteDesktop<'a>,
|
||||
session: Session<'a>,
|
||||
}
|
||||
|
||||
impl EventConsumer for DesktopPortalConsumer {
|
||||
fn consume(&mut self, _: crate::event::Event, _: crate::client::ClientHandle) {
|
||||
log::error!("xdg_desktop_portal backend not yet implemented!");
|
||||
impl<'a> DesktopPortalConsumer<'a> {
|
||||
pub async fn new() -> Result<DesktopPortalConsumer<'a>> {
|
||||
let proxy = RemoteDesktop::new().await?;
|
||||
let session = proxy.create_session().await?;
|
||||
proxy
|
||||
.select_devices(&session, DeviceType::Keyboard | DeviceType::Pointer)
|
||||
.await?;
|
||||
|
||||
let _ = proxy
|
||||
.start(&session, &WindowIdentifier::default())
|
||||
.await?
|
||||
.response()?;
|
||||
|
||||
Ok(Self { proxy, session })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> AsyncConsumer for DesktopPortalConsumer<'a> {
|
||||
async fn consume(&mut self, event: crate::event::Event, _client: crate::client::ClientHandle) {
|
||||
match event {
|
||||
crate::event::Event::Pointer(p) => {
|
||||
match p {
|
||||
crate::event::PointerEvent::Motion { time: _, relative_x, relative_y } => {
|
||||
if let Err(e) = self.proxy.notify_pointer_motion(&self.session, relative_x, relative_y).await {
|
||||
log::warn!("{e}");
|
||||
}
|
||||
},
|
||||
crate::event::PointerEvent::Button { time: _, button, state } => {
|
||||
let state = match state {
|
||||
0 => KeyState::Released,
|
||||
_ => KeyState::Pressed,
|
||||
};
|
||||
if let Err(e) = self.proxy.notify_pointer_button(&self.session, button as i32, state).await {
|
||||
log::warn!("{e}");
|
||||
}
|
||||
},
|
||||
crate::event::PointerEvent::Axis { time: _, axis, value } => {
|
||||
let axis = match axis {
|
||||
0 => Axis::Vertical,
|
||||
_ => Axis::Horizontal,
|
||||
};
|
||||
// TODO smooth scrolling
|
||||
if let Err(e) = self.proxy.notify_pointer_axis_discrete(&self.session, axis, value as i32).await {
|
||||
log::warn!("{e}");
|
||||
}
|
||||
|
||||
},
|
||||
crate::event::PointerEvent::Frame { } => {},
|
||||
}
|
||||
},
|
||||
crate::event::Event::Keyboard(k) => {
|
||||
match k {
|
||||
crate::event::KeyboardEvent::Key { time: _, key, state } => {
|
||||
let state = match state {
|
||||
0 => KeyState::Released,
|
||||
_ => KeyState::Pressed,
|
||||
};
|
||||
if let Err(e) = self.proxy.notify_keyboard_keycode(&self.session, key as i32, state).await {
|
||||
log::warn!("{e}");
|
||||
}
|
||||
},
|
||||
crate::event::KeyboardEvent::Modifiers { .. } => {
|
||||
// ignore
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn notify(&mut self, _: crate::client::ClientEvent) {}
|
||||
async fn notify(&mut self, _client: crate::client::ClientEvent) { }
|
||||
|
||||
async fn destroy(&mut self) {
|
||||
log::debug!("closing remote desktop session");
|
||||
if let Err(e) = self.session.close().await {
|
||||
log::error!("failed to close remote desktop session: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::env;
|
||||
|
||||
@@ -13,7 +15,12 @@ enum Backend {
|
||||
Libei,
|
||||
}
|
||||
|
||||
pub trait EventConsumer {
|
||||
pub enum EventConsumer {
|
||||
Sync(Box<dyn SyncConsumer>),
|
||||
Async(Box<dyn AsyncConsumer>),
|
||||
}
|
||||
|
||||
pub trait SyncConsumer {
|
||||
/// Event corresponding to an abstract `client_handle`
|
||||
fn consume(&mut self, event: Event, client_handle: ClientHandle);
|
||||
|
||||
@@ -21,9 +28,16 @@ pub trait EventConsumer {
|
||||
fn notify(&mut self, client_event: ClientEvent);
|
||||
}
|
||||
|
||||
pub fn create() -> Result<Box<dyn EventConsumer>> {
|
||||
#[async_trait]
|
||||
pub trait AsyncConsumer {
|
||||
async fn consume(&mut self, event: Event, client_handle: ClientHandle);
|
||||
async fn notify(&mut self, client_event: ClientEvent);
|
||||
async fn destroy(&mut self);
|
||||
}
|
||||
|
||||
pub async fn create() -> Result<EventConsumer> {
|
||||
#[cfg(windows)]
|
||||
return Ok(Box::new(consumer::windows::WindowsConsumer::new()));
|
||||
return Ok(EventConsumer::Sync(Box::new(consumer::windows::WindowsConsumer::new())));
|
||||
|
||||
#[cfg(unix)]
|
||||
let backend = match env::var("XDG_SESSION_TYPE") {
|
||||
@@ -75,25 +89,25 @@ pub fn create() -> Result<Box<dyn EventConsumer>> {
|
||||
#[cfg(not(feature = "libei"))]
|
||||
panic!("feature libei not enabled");
|
||||
#[cfg(feature = "libei")]
|
||||
Ok(Box::new(consumer::libei::LibeiConsumer::new()))
|
||||
Ok(EventConsumer::Sync(Box::new(consumer::libei::LibeiConsumer::new())))
|
||||
},
|
||||
Backend::RemoteDesktopPortal => {
|
||||
#[cfg(not(feature = "xdg_desktop_portal"))]
|
||||
panic!("feature xdg_desktop_portal not enabled");
|
||||
#[cfg(feature = "xdg_desktop_portal")]
|
||||
Ok(Box::new(consumer::xdg_desktop_portal::DesktopPortalConsumer::new()))
|
||||
Ok(EventConsumer::Async(Box::new(consumer::xdg_desktop_portal::DesktopPortalConsumer::new().await?)))
|
||||
},
|
||||
Backend::Wlroots => {
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
panic!("feature wayland not enabled");
|
||||
#[cfg(feature = "wayland")]
|
||||
Ok(Box::new(consumer::wlroots::WlrootsConsumer::new()?))
|
||||
Ok(EventConsumer::Sync(Box::new(consumer::wlroots::WlrootsConsumer::new()?)))
|
||||
},
|
||||
Backend::X11 => {
|
||||
#[cfg(not(feature = "x11"))]
|
||||
panic!("feature x11 not enabled");
|
||||
#[cfg(feature = "x11")]
|
||||
Ok(Box::new(consumer::x11::X11Consumer::new()))
|
||||
Ok(EventConsumer::Sync(Box::new(consumer::x11::X11Consumer::new())))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{error::Error, io::Result, collections::HashSet, time::{Duration, Instant}, net::IpAddr};
|
||||
use log;
|
||||
use tokio::{net::UdpSocket, io::ReadHalf, sync::mpsc::{Sender, Receiver}};
|
||||
use tokio::{net::UdpSocket, io::ReadHalf, signal, sync::mpsc::{Sender, Receiver}};
|
||||
|
||||
#[cfg(unix)]
|
||||
use tokio::net::UnixStream;
|
||||
@@ -26,7 +26,7 @@ pub struct Server {
|
||||
client_manager: ClientManager,
|
||||
state: State,
|
||||
frontend: FrontendListener,
|
||||
consumer: Box<dyn EventConsumer>,
|
||||
consumer: EventConsumer,
|
||||
producer: Box<dyn EventProducer>,
|
||||
socket: UdpSocket,
|
||||
frontend_rx: Receiver<FrontendEvent>,
|
||||
@@ -37,7 +37,7 @@ impl Server {
|
||||
pub async fn new(
|
||||
port: u16,
|
||||
frontend: FrontendListener,
|
||||
consumer: Box<dyn EventConsumer>,
|
||||
consumer: EventConsumer,
|
||||
producer: Box<dyn EventProducer>,
|
||||
) -> anyhow::Result<Self> {
|
||||
|
||||
@@ -102,6 +102,10 @@ impl Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = signal::ctrl_c() => {
|
||||
log::info!("terminating gracefully ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,9 +139,18 @@ impl Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = signal::ctrl_c() => {
|
||||
log::info!("terminating gracefully ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// destroy consumer
|
||||
if let EventConsumer::Async(c) = &mut self.consumer {
|
||||
c.destroy().await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -164,22 +177,31 @@ impl Server {
|
||||
client
|
||||
}
|
||||
|
||||
pub fn activate_client(&mut self, client: ClientHandle, active: bool) {
|
||||
pub async fn activate_client(&mut self, client: ClientHandle, active: bool) {
|
||||
if let Some(state) = self.client_manager.get_mut(client) {
|
||||
state.active = active;
|
||||
if state.active {
|
||||
self.producer.notify(ClientEvent::Create(client, state.client.pos));
|
||||
self.consumer.notify(ClientEvent::Create(client, state.client.pos));
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.notify(ClientEvent::Create(client, state.client.pos)),
|
||||
EventConsumer::Async(consumer) => consumer.notify(ClientEvent::Create(client, state.client.pos)).await,
|
||||
}
|
||||
} else {
|
||||
self.producer.notify(ClientEvent::Destroy(client));
|
||||
self.consumer.notify(ClientEvent::Destroy(client));
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.notify(ClientEvent::Destroy(client)),
|
||||
EventConsumer::Async(consumer) => consumer.notify(ClientEvent::Destroy(client)).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn remove_client(&mut self, client: ClientHandle) -> Option<ClientHandle> {
|
||||
self.producer.notify(ClientEvent::Destroy(client));
|
||||
self.consumer.notify(ClientEvent::Destroy(client));
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.notify(ClientEvent::Destroy(client)),
|
||||
EventConsumer::Async(consumer) => consumer.notify(ClientEvent::Destroy(client)).await,
|
||||
}
|
||||
if let Some(client) = self.client_manager.remove_client(client).map(|s| s.client.handle) {
|
||||
let notify = FrontendNotify::NotifyClientDelete(client);
|
||||
log::debug!("{notify:?}");
|
||||
@@ -208,9 +230,15 @@ impl Server {
|
||||
state.client.pos = pos;
|
||||
if state.active {
|
||||
self.producer.notify(ClientEvent::Destroy(client));
|
||||
self.consumer.notify(ClientEvent::Destroy(client));
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.notify(ClientEvent::Destroy(client)),
|
||||
EventConsumer::Async(consumer) => consumer.notify(ClientEvent::Destroy(client)).await,
|
||||
}
|
||||
self.producer.notify(ClientEvent::Create(client, pos));
|
||||
self.consumer.notify(ClientEvent::Create(client, pos));
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.notify(ClientEvent::Create(client, pos)),
|
||||
EventConsumer::Async(consumer) => consumer.notify(ClientEvent::Create(client, pos)).await,
|
||||
}
|
||||
}
|
||||
|
||||
// update port
|
||||
@@ -294,7 +322,10 @@ impl Server {
|
||||
}
|
||||
State::Receiving => {
|
||||
// consume event
|
||||
self.consumer.consume(event, handle);
|
||||
match &mut self.consumer {
|
||||
EventConsumer::Sync(consumer) => consumer.consume(event, handle),
|
||||
EventConsumer::Async(consumer) => consumer.consume(event, handle).await,
|
||||
}
|
||||
|
||||
// let the server know we are still alive once every second
|
||||
let last_replied = state.last_replied;
|
||||
@@ -421,7 +452,7 @@ impl Server {
|
||||
log::debug!("frontend: {event:?}");
|
||||
match event {
|
||||
FrontendEvent::AddClient(hostname, port, pos) => { self.add_client(hostname, HashSet::new(), port, pos).await; },
|
||||
FrontendEvent::ActivateClient(client, active) => self.activate_client(client, active),
|
||||
FrontendEvent::ActivateClient(client, active) => self.activate_client(client, active).await,
|
||||
FrontendEvent::DelClient(client) => { self.remove_client(client).await; },
|
||||
FrontendEvent::UpdateClient(client, hostname, port, pos) => self.update_client(client, hostname, port, pos).await,
|
||||
FrontendEvent::Enumerate() => self.enumerate().await,
|
||||
|
||||
@@ -27,10 +27,6 @@ pub fn run() -> Result<(), Box<dyn Error>> {
|
||||
// parse config file
|
||||
let config = Config::new()?;
|
||||
|
||||
// start producing and consuming events
|
||||
let producer = producer::create()?;
|
||||
let consumer = consumer::create()?;
|
||||
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
@@ -38,6 +34,10 @@ pub fn run() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// run async event loop
|
||||
runtime.block_on(LocalSet::new().run_until(async {
|
||||
// start producing and consuming events
|
||||
let producer = producer::create()?;
|
||||
let consumer = consumer::create().await?;
|
||||
|
||||
// create frontend communication adapter
|
||||
let frontend_adapter = FrontendListener::new().await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user