Compare commits
3 Commits
streaming-
...
linux-scre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a03d59be7c | ||
|
|
42a125aa19 | ||
|
|
3e0630e227 |
345
Cargo.lock
generated
345
Cargo.lock
generated
@@ -184,6 +184,16 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
"yansi-term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
@@ -1681,6 +1691,27 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.69.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"bitflags 2.6.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.12.1",
|
||||
"lazy_static",
|
||||
"lazycell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.70.1"
|
||||
@@ -2976,6 +3007,15 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cookie-factory"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2"
|
||||
dependencies = [
|
||||
"futures 0.3.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "copilot"
|
||||
version = "0.1.0"
|
||||
@@ -3069,6 +3109,19 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-helmer-fork"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32eb7c354ae9f6d437a6039099ce7ecd049337a8109b23d73e48e8ffba8e9cd5"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics-types 0.1.3",
|
||||
"foreign-types 0.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.3"
|
||||
@@ -3140,7 +3193,7 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bindgen 0.70.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3480,9 +3533,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
@@ -3494,7 +3547,7 @@ version = "3.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"nix 0.29.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@@ -3796,6 +3849,12 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
@@ -4517,7 +4576,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"smol",
|
||||
"sysinfo",
|
||||
"sysinfo 0.31.4",
|
||||
"ui",
|
||||
"urlencoding",
|
||||
"util",
|
||||
@@ -5295,7 +5354,7 @@ dependencies = [
|
||||
"ashpd",
|
||||
"async-task",
|
||||
"backtrace",
|
||||
"bindgen",
|
||||
"bindgen 0.70.1",
|
||||
"blade-graphics",
|
||||
"blade-macros",
|
||||
"blade-util",
|
||||
@@ -5342,6 +5401,7 @@ dependencies = [
|
||||
"raw-window-handle",
|
||||
"refineable",
|
||||
"resvg",
|
||||
"scap",
|
||||
"schemars",
|
||||
"seahash",
|
||||
"semantic_version",
|
||||
@@ -5906,7 +5966,7 @@ dependencies = [
|
||||
"http 1.1.0",
|
||||
"hyper 1.5.0",
|
||||
"hyper-util",
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"rustls-native-certs 0.8.0",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
@@ -6917,6 +6977,12 @@ dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "leb128"
|
||||
version = "0.2.5"
|
||||
@@ -6931,9 +6997,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.162"
|
||||
version = "0.2.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
@@ -7004,6 +7070,34 @@ dependencies = [
|
||||
"redox_syscall 0.5.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libspa"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65f3a4b81b2a2d8c7f300643676202debd1b7c929dbf5c9bb89402ea11d19810"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cc",
|
||||
"convert_case 0.6.0",
|
||||
"cookie-factory",
|
||||
"libc",
|
||||
"libspa-sys",
|
||||
"nix 0.27.1",
|
||||
"nom",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libspa-sys"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf0d9716420364790e85cbb9d3ac2c950bde16a7dd36f3209b7dfdfc4a24d01f"
|
||||
dependencies = [
|
||||
"bindgen 0.69.5",
|
||||
"cc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.30.1"
|
||||
@@ -7203,6 +7297,7 @@ dependencies = [
|
||||
"nanoid",
|
||||
"parking_lot",
|
||||
"postage",
|
||||
"scap",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@@ -7531,7 +7626,7 @@ name = "media"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen",
|
||||
"bindgen 0.70.1",
|
||||
"core-foundation 0.9.4",
|
||||
"ctor",
|
||||
"foreign-types 0.5.0",
|
||||
@@ -7822,6 +7917,17 @@ version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
@@ -8148,6 +8254,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
"objc_exception",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9250,6 +9386,34 @@ dependencies = [
|
||||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pipewire"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08e645ba5c45109106d56610b3ee60eb13a6f2beb8b74f8dc8186cf261788dda"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"libspa",
|
||||
"libspa-sys",
|
||||
"nix 0.27.1",
|
||||
"once_cell",
|
||||
"pipewire-sys",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pipewire-sys"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "849e188f90b1dda88fe2bfe1ad31fe5f158af2c98f80fb5d13726c44f3f01112"
|
||||
dependencies = [
|
||||
"bindgen 0.69.5",
|
||||
"libspa-sys",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.7.5"
|
||||
@@ -9903,7 +10067,7 @@ dependencies = [
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.0.0",
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"socket2 0.5.7",
|
||||
"thiserror 2.0.3",
|
||||
"tokio",
|
||||
@@ -9921,7 +10085,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"ring",
|
||||
"rustc-hash 2.0.0",
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.3",
|
||||
@@ -10346,7 +10510,7 @@ dependencies = [
|
||||
"settings",
|
||||
"shellexpand 2.1.2",
|
||||
"smol",
|
||||
"sysinfo",
|
||||
"sysinfo 0.31.4",
|
||||
"telemetry_events",
|
||||
"toml 0.8.19",
|
||||
"util",
|
||||
@@ -10480,7 +10644,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"rustls-native-certs 0.8.0",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"rustls-pki-types",
|
||||
@@ -10868,9 +11032,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.18"
|
||||
version = "0.23.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
|
||||
checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
@@ -11000,6 +11164,26 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scap"
|
||||
version = "0.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14ca85dd7aa5f0e11e093c1c32b306666a52903db1bd89aa6442967a03cd8bd2"
|
||||
dependencies = [
|
||||
"cocoa 0.25.0",
|
||||
"core-graphics-helmer-fork",
|
||||
"dbus",
|
||||
"objc",
|
||||
"pipewire",
|
||||
"rand 0.8.5",
|
||||
"screencapturekit",
|
||||
"screencapturekit-sys",
|
||||
"sysinfo 0.30.13",
|
||||
"tao-core-video-sys",
|
||||
"windows 0.58.0",
|
||||
"windows-capture",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.26"
|
||||
@@ -11052,6 +11236,29 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152"
|
||||
|
||||
[[package]]
|
||||
name = "screencapturekit"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a5eeeb57ac94960cfe5ff4c402be6585ae4c8d29a2cf41b276048c2e849d64e"
|
||||
dependencies = [
|
||||
"screencapturekit-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "screencapturekit-sys"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22411b57f7d49e7fe08025198813ee6fd65e1ee5eff4ebc7880c12c82bde4c60"
|
||||
dependencies = [
|
||||
"block",
|
||||
"dispatch",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scrypt"
|
||||
version = "0.11.0"
|
||||
@@ -11359,9 +11566,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.132"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
|
||||
dependencies = [
|
||||
"indexmap 2.6.0",
|
||||
"itoa",
|
||||
@@ -11915,9 +12122,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcfa89bea9500db4a0d038513d7a060566bfc51d46d1c014847049a45cce85e8"
|
||||
checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e"
|
||||
dependencies = [
|
||||
"sqlx-core",
|
||||
"sqlx-macros",
|
||||
@@ -11928,9 +12135,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-core"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d06e2f2bd861719b1f3f0c7dbe1d80c30bf59e76cf019f07d9014ed7eefb8e08"
|
||||
checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"bigdecimal",
|
||||
@@ -11956,7 +12163,7 @@ dependencies = [
|
||||
"paste",
|
||||
"percent-encoding",
|
||||
"rust_decimal",
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -11975,9 +12182,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f998a9defdbd48ed005a89362bd40dd2117502f15294f61c8d47034107dbbdc"
|
||||
checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -11988,9 +12195,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros-core"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d100558134176a2629d46cec0c8891ba0be8910f7896abfdb75ef4ab6f4e7ce"
|
||||
checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5"
|
||||
dependencies = [
|
||||
"dotenvy",
|
||||
"either",
|
||||
@@ -12014,9 +12221,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-mysql"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936cac0ab331b14cb3921c62156d913e4c15b74fb6ec0f3146bd4ef6e4fb3c12"
|
||||
checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
@@ -12061,9 +12268,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-postgres"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9734dbce698c67ecf67c442f768a5e90a49b2a4d61a9f1d59f73874bd4cf0710"
|
||||
checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
@@ -12105,9 +12312,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-sqlite"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75b419c3c1b1697833dd927bdc4c6545a620bc1bbafabd44e1efbe9afcd337e"
|
||||
checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"chrono",
|
||||
@@ -12490,6 +12697,21 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.30.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"ntapi",
|
||||
"once_cell",
|
||||
"rayon",
|
||||
"windows 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.31.4"
|
||||
@@ -12617,6 +12839,18 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bdb6fa0dfa67b38c1e66b7041ba9dcf23b99d8121907cd31c807a332f7a0bbb"
|
||||
|
||||
[[package]]
|
||||
name = "tao-core-video-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271450eb289cb4d8d0720c6ce70c72c8c858c93dd61fc625881616752e6b98f6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@@ -12733,7 +12967,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"settings",
|
||||
"smol",
|
||||
"sysinfo",
|
||||
"sysinfo 0.31.4",
|
||||
"task",
|
||||
"theme",
|
||||
"thiserror 1.0.69",
|
||||
@@ -13181,7 +13415,7 @@ version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||
dependencies = [
|
||||
"rustls 0.23.18",
|
||||
"rustls 0.23.16",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
@@ -15041,6 +15275,16 @@ dependencies = [
|
||||
"wasmtime-environ",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core 0.52.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.54.0"
|
||||
@@ -15071,6 +15315,20 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-capture"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6001b777f61cafce437201de46a019ed7f4afed3b669f02e5ce4e0759164cb3e"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"ctrlc",
|
||||
"parking_lot",
|
||||
"rayon",
|
||||
"thiserror 1.0.69",
|
||||
"windows 0.58.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
@@ -15857,6 +16115,15 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
||||
[[package]]
|
||||
name = "yansi-term"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi"
|
||||
version = "0.1.6"
|
||||
@@ -15920,7 +16187,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"nix",
|
||||
"nix 0.29.0",
|
||||
"ordered-stream",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
@@ -15957,7 +16224,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"nix",
|
||||
"nix 0.29.0",
|
||||
"ordered-stream",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
@@ -16085,7 +16352,7 @@ dependencies = [
|
||||
"markdown_preview",
|
||||
"menu",
|
||||
"mimalloc",
|
||||
"nix",
|
||||
"nix 0.29.0",
|
||||
"node_runtime",
|
||||
"notifications",
|
||||
"outline",
|
||||
@@ -16116,7 +16383,7 @@ dependencies = [
|
||||
"snippet_provider",
|
||||
"snippets_ui",
|
||||
"supermaven",
|
||||
"sysinfo",
|
||||
"sysinfo 0.31.4",
|
||||
"tab_switcher",
|
||||
"task",
|
||||
"tasks_ui",
|
||||
|
||||
@@ -441,6 +441,7 @@ rustc-demangle = "0.1.23"
|
||||
rust-embed = { version = "8.4", features = ["include-exclude"] }
|
||||
rustls = "0.21.12"
|
||||
rustls-native-certs = "0.8.0"
|
||||
scap = "0.0.7"
|
||||
schemars = { version = "0.8", features = ["impl_json_schema"] }
|
||||
semver = "1.0"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
|
||||
@@ -40,6 +40,7 @@ wayland = [
|
||||
"filedescriptor",
|
||||
"xkbcommon",
|
||||
"open",
|
||||
"scap",
|
||||
]
|
||||
x11 = [
|
||||
"blade-graphics",
|
||||
@@ -56,6 +57,7 @@ x11 = [
|
||||
"x11-clipboard",
|
||||
"filedescriptor",
|
||||
"open",
|
||||
"scap",
|
||||
]
|
||||
|
||||
|
||||
@@ -160,6 +162,7 @@ font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7"
|
||||
calloop = { version = "0.13.0" }
|
||||
filedescriptor = { version = "0.8.2", optional = true }
|
||||
open = { version = "5.2.0", optional = true }
|
||||
scap = { workspace = true, optional = true }
|
||||
|
||||
# Wayland
|
||||
calloop-wayland-source = { version = "0.3.0", optional = true }
|
||||
|
||||
@@ -237,20 +237,20 @@ pub trait PlatformDisplay: Send + Sync + Debug {
|
||||
}
|
||||
|
||||
/// A source of on-screen video content that can be captured.
|
||||
pub trait ScreenCaptureSource {
|
||||
pub trait ScreenCaptureSource: Send {
|
||||
/// Returns the video resolution of this source.
|
||||
fn resolution(&self) -> Result<Size<Pixels>>;
|
||||
fn resolution(&self) -> Result<Size<DevicePixels>>;
|
||||
|
||||
/// Start capture video from this source, invoking the given callback
|
||||
/// with each frame.
|
||||
fn stream(
|
||||
&self,
|
||||
frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
|
||||
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
|
||||
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>>;
|
||||
}
|
||||
|
||||
/// A video stream captured from a screen.
|
||||
pub trait ScreenCaptureStream {}
|
||||
pub trait ScreenCaptureStream: Send {}
|
||||
|
||||
/// A frame of video captured from a screen.
|
||||
pub struct ScreenCaptureFrame(pub PlatformScreenCaptureFrame);
|
||||
|
||||
@@ -21,4 +21,4 @@ pub(crate) use wayland::*;
|
||||
#[cfg(feature = "x11")]
|
||||
pub(crate) use x11::*;
|
||||
|
||||
pub(crate) type PlatformScreenCaptureFrame = ();
|
||||
pub type PlatformScreenCaptureFrame = platform::ScapFrame;
|
||||
|
||||
@@ -3,11 +3,14 @@ use std::rc::Rc;
|
||||
|
||||
use calloop::{EventLoop, LoopHandle};
|
||||
|
||||
use futures::channel::oneshot;
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::platform::linux::LinuxClient;
|
||||
use crate::platform::{LinuxCommon, PlatformWindow};
|
||||
use crate::{AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, WindowParams};
|
||||
use crate::{
|
||||
AnyWindowHandle, CursorStyle, DisplayId, PlatformDisplay, ScreenCaptureSource, WindowParams,
|
||||
};
|
||||
|
||||
pub struct HeadlessClientState {
|
||||
pub(crate) _loop_handle: LoopHandle<'static, HeadlessClient>,
|
||||
@@ -59,6 +62,17 @@ impl LinuxClient for HeadlessClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn screen_capture_sources(
|
||||
&self,
|
||||
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
|
||||
let (mut tx, rx) = oneshot::channel();
|
||||
tx.send(Err(anyhow::anyhow!(
|
||||
"headless client does not support screen capture."
|
||||
)))
|
||||
.ok();
|
||||
rx
|
||||
}
|
||||
|
||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use std::ops::{Deref, DerefMut};
|
||||
use std::os::fd::{AsFd, AsRawFd, FromRawFd};
|
||||
use std::panic::Location;
|
||||
use std::rc::Weak;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
@@ -32,11 +33,12 @@ use xkbcommon::xkb::{self, Keycode, Keysym, State};
|
||||
|
||||
use crate::platform::NoopTextSystem;
|
||||
use crate::{
|
||||
px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||
ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers, OwnedMenu,
|
||||
PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformInputHandler, PlatformTextSystem,
|
||||
PlatformWindow, Point, PromptLevel, Result, ScreenCaptureSource, SemanticVersion, SharedString,
|
||||
Size, Task, WindowAppearance, WindowOptions, WindowParams,
|
||||
px, size, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle,
|
||||
DevicePixels, DisplayId, ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu,
|
||||
MenuItem, Modifiers, OwnedMenu, PathPromptOptions, Pixels, Platform, PlatformDisplay,
|
||||
PlatformInputHandler, PlatformTextSystem, PlatformWindow, Point, PromptLevel, Result,
|
||||
ScreenCaptureSource, ScreenCaptureStream, SemanticVersion, SharedString, Size, Task,
|
||||
WindowAppearance, WindowOptions, WindowParams,
|
||||
};
|
||||
|
||||
pub(crate) const SCROLL_LINES: f32 = 3.0;
|
||||
@@ -56,6 +58,9 @@ pub trait LinuxClient {
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
|
||||
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
|
||||
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>>;
|
||||
fn screen_capture_sources(
|
||||
&self,
|
||||
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>>;
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
@@ -245,9 +250,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
fn screen_capture_sources(
|
||||
&self,
|
||||
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
|
||||
let (mut tx, rx) = oneshot::channel();
|
||||
tx.send(Err(anyhow!("screen capture not implemented"))).ok();
|
||||
rx
|
||||
self.screen_capture_sources()
|
||||
}
|
||||
|
||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||
@@ -843,6 +846,31 @@ impl Modifiers {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_scap_capturer(target: Option<scap::Target>) -> anyhow::Result<scap::capturer::Capturer> {
|
||||
Ok(scap::capturer::Capturer::build(scap::capturer::Options {
|
||||
fps: 60,
|
||||
show_cursor: true,
|
||||
show_highlight: true,
|
||||
output_type: scap::frame::FrameType::YUVFrame,
|
||||
output_resolution: scap::capturer::Resolution::Captured,
|
||||
crop_area: None,
|
||||
target,
|
||||
excluded_targets: None,
|
||||
})?)
|
||||
}
|
||||
|
||||
pub struct ScapFrame(pub scap::frame::Frame);
|
||||
|
||||
pub struct ScapStream(pub Arc<AtomicBool>);
|
||||
|
||||
impl ScreenCaptureStream for ScapStream {}
|
||||
|
||||
impl Drop for ScapStream {
|
||||
fn drop(&mut self) {
|
||||
self.0.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -2,6 +2,7 @@ mod client;
|
||||
mod clipboard;
|
||||
mod cursor;
|
||||
mod display;
|
||||
mod screen_capture;
|
||||
mod serial;
|
||||
mod window;
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ use calloop_wayland_source::WaylandSource;
|
||||
use collections::HashMap;
|
||||
use filedescriptor::Pipe;
|
||||
|
||||
use futures::channel::oneshot;
|
||||
|
||||
use http_client::Url;
|
||||
use smallvec::SmallVec;
|
||||
use util::ResultExt;
|
||||
@@ -68,6 +70,7 @@ use crate::platform::linux::wayland::clipboard::{
|
||||
Clipboard, DataOffer, FILE_LIST_MIME_TYPE, TEXT_MIME_TYPE,
|
||||
};
|
||||
use crate::platform::linux::wayland::cursor::Cursor;
|
||||
use crate::platform::linux::wayland::screen_capture::wayland_screen_capture_sources;
|
||||
use crate::platform::linux::wayland::serial::{SerialKind, SerialTracker};
|
||||
use crate::platform::linux::wayland::window::WaylandWindow;
|
||||
use crate::platform::linux::xdg_desktop_portal::{Event as XDPEvent, XDPEventSource};
|
||||
@@ -78,16 +81,13 @@ use crate::platform::linux::{
|
||||
};
|
||||
use crate::platform::PlatformWindow;
|
||||
use crate::{
|
||||
point, px, size, Bounds, DevicePixels, FileDropEvent, ForegroundExecutor, MouseExitEvent, Size,
|
||||
point, px, size, AnyWindowHandle, Bounds, CursorStyle, DevicePixels, DisplayId, FileDropEvent,
|
||||
ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon, Modifiers,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent,
|
||||
MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScaledPixels,
|
||||
ScreenCaptureSource, ScrollDelta, ScrollWheelEvent, Size, TouchPhase, WindowParams,
|
||||
DOUBLE_CLICK_INTERVAL, SCROLL_LINES,
|
||||
};
|
||||
use crate::{
|
||||
AnyWindowHandle, CursorStyle, DisplayId, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||
NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScaledPixels, ScrollDelta,
|
||||
ScrollWheelEvent, TouchPhase,
|
||||
};
|
||||
use crate::{LinuxCommon, WindowParams};
|
||||
|
||||
/// Used to convert evdev scancode to xkb scancode
|
||||
const MIN_KEYCODE: u32 = 8;
|
||||
@@ -617,6 +617,12 @@ impl LinuxClient for WaylandClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn screen_capture_sources(
|
||||
&self,
|
||||
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
|
||||
wayland_screen_capture_sources()
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
|
||||
124
crates/gpui/src/platform/linux/wayland/screen_capture.rs
Normal file
124
crates/gpui/src/platform/linux/wayland/screen_capture.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
use crate::{
|
||||
new_scap_capturer, size, DevicePixels, ScapFrame, ScapStream, ScreenCaptureFrame,
|
||||
ScreenCaptureSource, ScreenCaptureStream, Size,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use futures::channel::oneshot;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct ScapCapturer {
|
||||
stream_tx: std::sync::mpsc::Sender<(
|
||||
oneshot::Sender<anyhow::Result<Box<dyn ScreenCaptureStream>>>,
|
||||
Box<dyn Fn(ScreenCaptureFrame) + Send>,
|
||||
)>,
|
||||
size: Size<DevicePixels>,
|
||||
}
|
||||
|
||||
impl ScreenCaptureSource for ScapCapturer {
|
||||
fn resolution(&self) -> anyhow::Result<Size<DevicePixels>> {
|
||||
Ok(self.size)
|
||||
}
|
||||
|
||||
fn stream(
|
||||
&self,
|
||||
frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
|
||||
) -> oneshot::Receiver<anyhow::Result<Box<dyn ScreenCaptureStream>>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.stream_tx.send((tx, frame_callback)).ok();
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
||||
/// Requests that wayland prompts the user about which screen or window to capture. The receiver
|
||||
/// will be filled with a capture source.
|
||||
pub fn wayland_screen_capture_sources(
|
||||
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
|
||||
let (mut tx, result_rx) = oneshot::channel();
|
||||
|
||||
// Due to use of blocking APIs a dedicated thread is used.
|
||||
std::thread::spawn(|| {
|
||||
let (stream_tx, stream_rx) = std::sync::mpsc::channel();
|
||||
|
||||
let screen_capturer = util::maybe!({
|
||||
// TODO: needed?
|
||||
if !scap::has_permission() {
|
||||
if !scap::request_permission() {
|
||||
Err(anyhow!("No permissions to share screen"))?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut capturer = new_scap_capturer(None)?;
|
||||
|
||||
// Screen capture needs to start immediately so that the size can be determined.
|
||||
// In Zed the size is needed in order to initialize the LiveKit video channel.
|
||||
//
|
||||
// FIXME: can this be done way simpler in capture_local_video_track?
|
||||
capturer.start_capture();
|
||||
let size = match capturer.get_next_frame() {
|
||||
Ok(frame) => get_frame_size(&frame),
|
||||
Err(std::sync::mpsc::RecvError) => Err(anyhow!(
|
||||
"Failed to get first frame of screenshare to get the size."
|
||||
))?,
|
||||
};
|
||||
|
||||
Ok((
|
||||
capturer,
|
||||
vec![Box::new(ScapCapturer { stream_tx, size }) as Box<dyn ScreenCaptureSource>],
|
||||
))
|
||||
});
|
||||
|
||||
match screen_capturer {
|
||||
Err(e) => {
|
||||
tx.send(Err(e)).ok();
|
||||
}
|
||||
Ok((mut capturer, sources)) => {
|
||||
tx.send(Ok(sources)).ok();
|
||||
|
||||
while let Ok((tx, callback)) = stream_rx.recv() {
|
||||
let cancel_stream = Arc::new(AtomicBool::new(false));
|
||||
tx.send(Ok(Box::new(ScapStream(cancel_stream.clone()))))
|
||||
.ok();
|
||||
while cancel_stream.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
match capturer.get_next_frame() {
|
||||
Ok(frame) => callback(ScreenCaptureFrame(ScapFrame(frame))),
|
||||
Err(std::sync::mpsc::RecvError) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
capturer.stop_capture();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result_rx
|
||||
}
|
||||
|
||||
fn get_frame_size(frame: &scap::frame::Frame) -> Size<DevicePixels> {
|
||||
match frame {
|
||||
scap::frame::Frame::YUVFrame(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::RGB(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::RGBx(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::XBGR(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::BGRx(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::BGR0(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
scap::frame::Frame::BGRA(frame) => {
|
||||
size(DevicePixels(frame.width), DevicePixels(frame.height))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
mod client;
|
||||
mod display;
|
||||
mod event;
|
||||
mod screen_capture;
|
||||
mod window;
|
||||
mod xim_handler;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use calloop::generic::{FdWrapper, Generic};
|
||||
use calloop::{EventLoop, LoopHandle, RegistrationToken};
|
||||
|
||||
use collections::HashMap;
|
||||
use futures::channel::oneshot;
|
||||
use http_client::Url;
|
||||
use smallvec::SmallVec;
|
||||
use util::ResultExt;
|
||||
@@ -39,7 +40,7 @@ use crate::{
|
||||
modifiers_from_xinput_info, point, px, AnyWindowHandle, Bounds, ClipboardItem, CursorStyle,
|
||||
DisplayId, FileDropEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, Pixels,
|
||||
Platform, PlatformDisplay, PlatformInput, Point, RequestFrameOptions, ScaledPixels,
|
||||
ScrollDelta, Size, TouchPhase, WindowParams, X11Window,
|
||||
ScreenCaptureSource, ScrollDelta, Size, TouchPhase, WindowParams, X11Window,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -49,6 +50,7 @@ use super::{
|
||||
use super::{X11Display, X11WindowStatePtr, XcbAtoms};
|
||||
use super::{XimCallbackEvent, XimHandler};
|
||||
use crate::platform::linux::platform::{DOUBLE_CLICK_INTERVAL, SCROLL_LINES};
|
||||
use crate::platform::linux::x11::screen_capture::x11_screen_capture_sources;
|
||||
use crate::platform::linux::xdg_desktop_portal::{Event as XDPEvent, XDPEventSource};
|
||||
use crate::platform::linux::{
|
||||
get_xkb_compose_state, is_within_click_distance, open_uri_internal, reveal_path_internal,
|
||||
@@ -1250,6 +1252,14 @@ impl LinuxClient for X11Client {
|
||||
f(&mut self.0.borrow_mut().common)
|
||||
}
|
||||
|
||||
fn screen_capture_sources(
|
||||
&self,
|
||||
) -> oneshot::Receiver<anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>>> {
|
||||
let (mut tx, result_rx) = oneshot::channel();
|
||||
tx.send(x11_screen_capture_sources()).ok();
|
||||
result_rx
|
||||
}
|
||||
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
||||
let state = self.0.borrow();
|
||||
let setup = state.xcb_connection.setup();
|
||||
|
||||
82
crates/gpui/src/platform/linux/x11/screen_capture.rs
Normal file
82
crates/gpui/src/platform/linux/x11/screen_capture.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use crate::{
|
||||
new_scap_capturer, DevicePixels, ScapFrame, ScapStream, ScreenCaptureFrame,
|
||||
ScreenCaptureSource, Size,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use futures::channel::oneshot;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct X11ScreenCaptureSource {
|
||||
target: scap::Target,
|
||||
size: Size<DevicePixels>,
|
||||
}
|
||||
|
||||
impl ScreenCaptureSource for X11ScreenCaptureSource {
|
||||
fn resolution(&self) -> anyhow::Result<Size<DevicePixels>> {
|
||||
Ok(self.size)
|
||||
}
|
||||
|
||||
fn stream(
|
||||
&self,
|
||||
frame_callback: Box<dyn Fn(crate::ScreenCaptureFrame) + Send>,
|
||||
) -> oneshot::Receiver<anyhow::Result<Box<dyn crate::ScreenCaptureStream>>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
// TODO: can clone be avoided here and elsewhere?
|
||||
let target = self.target.clone();
|
||||
// Due to use of blocking APIs a dedicated thread is used.
|
||||
std::thread::spawn(move || {
|
||||
let cancel_stream = Arc::new(AtomicBool::new(false));
|
||||
let mut capturer = match new_scap_capturer(Some(target)) {
|
||||
Ok(capturer) => {
|
||||
tx.send(Ok(Box::new(ScapStream(cancel_stream.clone()))
|
||||
as Box<dyn crate::ScreenCaptureStream>))
|
||||
.ok();
|
||||
capturer
|
||||
}
|
||||
Err(e) => {
|
||||
tx.send(Err(e)).ok();
|
||||
return;
|
||||
}
|
||||
};
|
||||
while cancel_stream.load(std::sync::atomic::Ordering::SeqCst) {
|
||||
match capturer.get_next_frame() {
|
||||
Ok(frame) => frame_callback(ScreenCaptureFrame(ScapFrame(frame))),
|
||||
Err(std::sync::mpsc::RecvError) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
capturer.stop_capture();
|
||||
});
|
||||
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x11_screen_capture_sources() -> anyhow::Result<Vec<Box<dyn ScreenCaptureSource>>> {
|
||||
if !scap::has_permission() {
|
||||
if !scap::request_permission() {
|
||||
Err(anyhow!("No permissions to share screen"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(mgsloan): Handle window capture too? On Mac it's only displays.
|
||||
Ok(scap::get_all_targets()
|
||||
.iter()
|
||||
.filter_map(|target| match target {
|
||||
scap::Target::Display(display) => {
|
||||
let size = Size {
|
||||
width: DevicePixels(display.width as i32),
|
||||
height: DevicePixels(display.height as i32),
|
||||
};
|
||||
Some(Box::new(X11ScreenCaptureSource {
|
||||
target: target.clone(),
|
||||
size,
|
||||
}) as Box<dyn ScreenCaptureSource>)
|
||||
}
|
||||
scap::Target::Window(_) => None,
|
||||
})
|
||||
.collect::<Vec<_>>())
|
||||
}
|
||||
@@ -43,7 +43,7 @@ const FRAME_CALLBACK_IVAR: &str = "frame_callback";
|
||||
const SCStreamOutputTypeScreen: NSInteger = 0;
|
||||
|
||||
impl ScreenCaptureSource for MacScreenCaptureSource {
|
||||
fn resolution(&self) -> Result<Size<Pixels>> {
|
||||
fn resolution(&self) -> Result<Size<DevicePixels>> {
|
||||
unsafe {
|
||||
let width: i64 = msg_send![self.sc_display, width];
|
||||
let height: i64 = msg_send![self.sc_display, height];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
px, size, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor,
|
||||
size, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, ForegroundExecutor,
|
||||
Keymap, Platform, PlatformDisplay, PlatformTextSystem, ScreenCaptureFrame, ScreenCaptureSource,
|
||||
ScreenCaptureStream, Task, TestDisplay, TestWindow, WindowAppearance, WindowParams,
|
||||
};
|
||||
@@ -46,13 +46,13 @@ pub struct TestScreenCaptureSource {}
|
||||
pub struct TestScreenCaptureStream {}
|
||||
|
||||
impl ScreenCaptureSource for TestScreenCaptureSource {
|
||||
fn resolution(&self) -> Result<crate::Size<crate::Pixels>> {
|
||||
Ok(size(px(1.), px(1.)))
|
||||
fn resolution(&self) -> Result<crate::Size<crate::DevicePixels>> {
|
||||
Ok(size(crate::DevicePixels(1), crate::DevicePixels(1)))
|
||||
}
|
||||
|
||||
fn stream(
|
||||
&self,
|
||||
_frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
|
||||
_frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,
|
||||
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>> {
|
||||
let (mut tx, rx) = oneshot::channel();
|
||||
let stream = TestScreenCaptureStream {};
|
||||
|
||||
@@ -21,5 +21,3 @@ pub(crate) use window::*;
|
||||
pub(crate) use wrapper::*;
|
||||
|
||||
pub(crate) use windows::Win32::Foundation::HWND;
|
||||
|
||||
pub(crate) type PlatformScreenCaptureFrame = ();
|
||||
|
||||
@@ -45,6 +45,7 @@ image.workspace = true
|
||||
|
||||
[target.'cfg(not(target_os = "windows"))'.dependencies]
|
||||
livekit.workspace = true
|
||||
scap.workspace = true
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation.workspace = true
|
||||
|
||||
@@ -311,8 +311,8 @@ impl LivekitWindow {
|
||||
let sources = cx.screen_capture_sources();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let sources = sources.await.unwrap()?;
|
||||
let source = sources.into_iter().next().unwrap();
|
||||
let (track, stream) = capture_local_video_track(&*source).await?;
|
||||
let mut source = sources.into_iter().next().unwrap();
|
||||
let (track, stream) = capture_local_video_track(&mut *source).await?;
|
||||
let publication = participant
|
||||
.publish_track(
|
||||
LocalTrack::Video(track),
|
||||
|
||||
@@ -518,8 +518,26 @@ fn video_frame_buffer_to_webrtc(frame: ScreenCaptureFrame) -> Option<impl AsRef<
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
fn video_frame_buffer_to_webrtc(_frame: ScreenCaptureFrame) -> Option<impl AsRef<dyn VideoBuffer>> {
|
||||
None as Option<Box<dyn VideoBuffer>>
|
||||
fn video_frame_buffer_to_webrtc(frame: ScreenCaptureFrame) -> Option<impl AsRef<dyn VideoBuffer>> {
|
||||
use livekit::webrtc::prelude::NV12Buffer;
|
||||
match frame.0 .0 {
|
||||
scap::frame::Frame::YUVFrame(yuvframe) => {
|
||||
let mut buffer = NV12Buffer::with_strides(
|
||||
yuvframe.width as u32,
|
||||
yuvframe.height as u32,
|
||||
yuvframe.luminance_stride as u32,
|
||||
yuvframe.chrominance_stride as u32,
|
||||
);
|
||||
let (luminance, chrominance) = buffer.data_mut();
|
||||
luminance.copy_from_slice(yuvframe.luminance_bytes.as_slice());
|
||||
chrominance.copy_from_slice(yuvframe.chrominance_bytes.as_slice());
|
||||
Some(buffer)
|
||||
}
|
||||
_ => {
|
||||
log::error!("Expected YUV frame from scap but got some other format.");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait DeviceChangeListenerApi: Stream<Item = ()> + Sized {
|
||||
|
||||
@@ -297,8 +297,8 @@ impl TitleBar {
|
||||
let can_use_microphone = room.can_use_microphone(cx);
|
||||
let can_share_projects = room.can_share_projects();
|
||||
let screen_sharing_supported = match self.platform_style {
|
||||
PlatformStyle::Mac => true,
|
||||
PlatformStyle::Linux | PlatformStyle::Windows => false,
|
||||
PlatformStyle::Mac | PlatformStyle::Linux => true,
|
||||
PlatformStyle::Windows => false,
|
||||
};
|
||||
|
||||
let mut children = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user