Linux: file dialogs (#7852)

This PR implements linux file dialogs and open/reveal actions.

| Open folder | Reveal path |
| --- | --- |
| ![Screenshot from 2024-02-15
16-50-49](https://github.com/zed-industries/zed/assets/1423607/b4260574-d841-4ded-821d-521f507916d1)
| ![Screenshot from 2024-02-15
16-51-36](https://github.com/zed-industries/zed/assets/1423607/1f32f451-7def-423a-9d69-de2876285b60)
|

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Rom Grk 2024-02-16 13:34:54 -05:00 committed by GitHub
parent 43e8fdbe82
commit bea36918f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 435 additions and 40 deletions

404
Cargo.lock generated
View File

@ -300,6 +300,24 @@ dependencies = [
"raw-window-metal",
]
[[package]]
name = "ashpd"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01992ad7774250d5b7fe214e2676cb99bf92564436d8135ab44fe815e71769a9"
dependencies = [
"async-fs 2.1.1",
"async-net 2.0.0",
"enumflags2",
"futures-channel",
"futures-util",
"rand 0.8.5",
"serde",
"serde_repr",
"url",
"zbus",
]
[[package]]
name = "assets"
version = "0.1.0"
@ -356,11 +374,21 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61"
dependencies = [
"event-listener",
"event-listener 2.5.3",
"futures-core",
"parking_lot 0.12.1",
]
[[package]]
name = "async-broadcast"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
dependencies = [
"event-listener 2.5.3",
"futures-core",
]
[[package]]
name = "async-channel"
version = "1.9.0"
@ -368,7 +396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
dependencies = [
"concurrent-queue",
"event-listener",
"event-listener 2.5.3",
"futures-core",
]
@ -404,11 +432,11 @@ version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb"
dependencies = [
"async-lock",
"async-lock 2.8.0",
"async-task",
"concurrent-queue",
"fastrand 1.9.0",
"futures-lite",
"futures-lite 1.13.0",
"slab",
]
@ -418,10 +446,21 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
dependencies = [
"async-lock",
"async-lock 2.8.0",
"autocfg",
"blocking",
"futures-lite",
"futures-lite 1.13.0",
]
[[package]]
name = "async-fs"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc19683171f287921f2405677dd2ed2549c3b3bda697a563ebc3a121ace2aba1"
dependencies = [
"async-lock 3.3.0",
"blocking",
"futures-lite 2.0.0",
]
[[package]]
@ -432,10 +471,10 @@ checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
dependencies = [
"async-channel",
"async-executor",
"async-io",
"async-lock",
"async-io 1.13.0",
"async-lock 2.8.0",
"blocking",
"futures-lite",
"futures-lite 1.13.0",
"once_cell",
]
@ -445,11 +484,11 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
dependencies = [
"async-lock",
"async-lock 2.8.0",
"autocfg",
"cfg-if 1.0.0",
"concurrent-queue",
"futures-lite",
"futures-lite 1.13.0",
"log",
"parking",
"polling 2.8.0",
@ -459,13 +498,43 @@ dependencies = [
"waker-fn",
]
[[package]]
name = "async-io"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65"
dependencies = [
"async-lock 3.3.0",
"cfg-if 1.0.0",
"concurrent-queue",
"futures-io",
"futures-lite 2.0.0",
"parking",
"polling 3.3.2",
"rustix 0.38.30",
"slab",
"tracing",
"windows-sys 0.52.0",
]
[[package]]
name = "async-lock"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
dependencies = [
"event-listener",
"event-listener 2.5.3",
]
[[package]]
name = "async-lock"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b"
dependencies = [
"event-listener 4.0.3",
"event-listener-strategy",
"pin-project-lite 0.2.13",
]
[[package]]
@ -486,10 +555,21 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f"
dependencies = [
"async-io",
"async-io 1.13.0",
"autocfg",
"blocking",
"futures-lite",
"futures-lite 1.13.0",
]
[[package]]
name = "async-net"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
dependencies = [
"async-io 2.3.1",
"blocking",
"futures-lite 2.0.0",
]
[[package]]
@ -507,13 +587,13 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
dependencies = [
"async-io",
"async-lock",
"async-io 1.13.0",
"async-lock 2.8.0",
"autocfg",
"blocking",
"cfg-if 1.0.0",
"event-listener",
"futures-lite",
"event-listener 2.5.3",
"futures-lite 1.13.0",
"rustix 0.37.23",
"signal-hook",
"windows-sys 0.48.0",
@ -549,13 +629,13 @@ checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
dependencies = [
"async-channel",
"async-global-executor",
"async-io",
"async-lock",
"async-io 1.13.0",
"async-lock 2.8.0",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"futures-lite 1.13.0",
"gloo-timers",
"kv-log-macro",
"log",
@ -1384,11 +1464,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
dependencies = [
"async-channel",
"async-lock",
"async-lock 2.8.0",
"async-task",
"atomic-waker",
"fastrand 1.9.0",
"futures-lite",
"futures-lite 1.13.0",
"log",
]
@ -1562,7 +1642,7 @@ name = "call"
version = "0.1.0"
dependencies = [
"anyhow",
"async-broadcast",
"async-broadcast 0.4.1",
"audio",
"client",
"collections",
@ -3058,6 +3138,27 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "enumflags2"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d"
dependencies = [
"enumflags2_derive",
"serde",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "env_logger"
version = "0.9.3"
@ -3141,6 +3242,27 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "event-listener"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite 0.2.13",
]
[[package]]
name = "event-listener-strategy"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3"
dependencies = [
"event-listener 4.0.3",
"pin-project-lite 0.2.13",
]
[[package]]
name = "extension"
version = "0.1.0"
@ -3691,6 +3813,21 @@ dependencies = [
"waker-fn",
]
[[package]]
name = "futures-lite"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c1155db57329dca6d018b61e76b1488ce9a2e5e44028cac420a5898f4fcef63"
dependencies = [
"fastrand 2.0.0",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite 0.2.13",
"waker-fn",
]
[[package]]
name = "futures-macro"
version = "0.3.30"
@ -3935,6 +4072,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"as-raw-xcb-connection",
"ashpd",
"async-task",
"backtrace",
"bindgen 0.65.1",
@ -3969,6 +4107,7 @@ dependencies = [
"metal 0.21.0",
"num_cpus",
"objc",
"open",
"ordered-float 2.10.0",
"parking",
"parking_lot 0.11.2",
@ -4531,6 +4670,25 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
[[package]]
name = "is-docker"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
dependencies = [
"once_cell",
]
[[package]]
name = "is-wsl"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
dependencies = [
"is-docker",
"once_cell",
]
[[package]]
name = "isahc"
version = "1.7.2"
@ -4543,8 +4701,8 @@ dependencies = [
"curl",
"curl-sys",
"encoding_rs",
"event-listener",
"futures-lite",
"event-listener 2.5.3",
"futures-lite 1.13.0",
"http 0.2.9",
"log",
"mime",
@ -4730,7 +4888,7 @@ name = "language"
version = "0.1.0"
dependencies = [
"anyhow",
"async-broadcast",
"async-broadcast 0.4.1",
"async-trait",
"client",
"clock",
@ -4987,7 +5145,7 @@ name = "live_kit_client"
version = "0.1.0"
dependencies = [
"anyhow",
"async-broadcast",
"async-broadcast 0.4.1",
"async-trait",
"block",
"byteorder",
@ -5239,6 +5397,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "memoffset"
version = "0.9.0"
@ -5606,6 +5773,18 @@ dependencies = [
"libc",
]
[[package]]
name = "nix"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
"bitflags 1.3.2",
"cfg-if 1.0.0",
"libc",
"memoffset 0.7.1",
]
[[package]]
name = "nix"
version = "0.27.1"
@ -5978,6 +6157,17 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "open"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90878fb664448b54c4e592455ad02831e23a3f7e157374a8b95654731aac7349"
dependencies = [
"is-wsl",
"libc",
"pathdiff",
]
[[package]]
name = "openssl"
version = "0.10.57"
@ -6040,6 +6230,16 @@ dependencies = [
"num-traits",
]
[[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 0.2.13",
]
[[package]]
name = "os_str_bytes"
version = "6.5.1"
@ -6232,6 +6432,12 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "pathfinder_color"
version = "0.5.0"
@ -7499,7 +7705,7 @@ name = "rpc"
version = "0.1.0"
dependencies = [
"anyhow",
"async-lock",
"async-lock 2.8.0",
"async-tungstenite",
"base64 0.13.1",
"clock",
@ -8469,13 +8675,13 @@ checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1"
dependencies = [
"async-channel",
"async-executor",
"async-fs",
"async-io",
"async-lock",
"async-net",
"async-fs 1.6.0",
"async-io 1.13.0",
"async-lock 2.8.0",
"async-net 1.7.0",
"async-process",
"blocking",
"futures-lite",
"futures-lite 1.13.0",
]
[[package]]
@ -8484,7 +8690,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "847d777e2c6c166bad26264479e80a9820f3d364fcb4a0e23cd57bbfa8e94961"
dependencies = [
"async-io",
"async-io 1.13.0",
"pin-project-lite 0.1.12",
]
@ -8636,7 +8842,7 @@ dependencies = [
"crossbeam-queue",
"dotenvy",
"either",
"event-listener",
"event-listener 2.5.3",
"futures-channel",
"futures-core",
"futures-intrusive",
@ -10287,6 +10493,17 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "uds_windows"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
dependencies = [
"memoffset 0.9.0",
"tempfile",
"winapi 0.3.9",
]
[[package]]
name = "ui"
version = "0.1.0"
@ -11480,6 +11697,16 @@ dependencies = [
"quick-xml 0.30.0",
]
[[package]]
name = "xdg-home"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "xkbcommon"
version = "0.7.0"
@ -11534,6 +11761,72 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "zbus"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c45d06ae3b0f9ba1fb2671268b975557d8f5a84bb5ec6e43964f87e763d8bca8"
dependencies = [
"async-broadcast 0.5.1",
"async-executor",
"async-fs 1.6.0",
"async-io 1.13.0",
"async-lock 2.8.0",
"async-process",
"async-recursion 1.0.5",
"async-task",
"async-trait",
"blocking",
"byteorder",
"derivative",
"enumflags2",
"event-listener 2.5.3",
"futures-core",
"futures-sink",
"futures-util",
"hex",
"nix 0.26.4",
"once_cell",
"ordered-stream",
"rand 0.8.5",
"serde",
"serde_repr",
"sha1",
"static_assertions",
"tracing",
"uds_windows",
"winapi 0.3.9",
"xdg-home",
"zbus_macros",
"zbus_names",
"zvariant",
]
[[package]]
name = "zbus_macros"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4a1ba45ed0ad344b85a2bb5a1fe9830aed23d67812ea39a586e7d0136439c7d"
dependencies = [
"proc-macro-crate 1.3.1",
"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 = "zed"
version = "0.124.0"
@ -11770,3 +12063,42 @@ dependencies = [
"libc",
"pkg-config",
]
[[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 1.3.1",
"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",
]

View File

@ -96,6 +96,8 @@ objc = "0.2"
[target.'cfg(target_os = "linux")'.dependencies]
flume = "0.11"
open = "5.0.1"
ashpd = "0.7.0"
# todo!(linux) - Technically do not use `randr`, but it doesn't compile otherwise
xcb = { version = "1.3", features = ["as-raw-xcb-connection", "present", "randr", "xkb"] }
wayland-client= { version = "0.31.2" }

View File

@ -8,6 +8,7 @@ use std::{
time::Duration,
};
use ashpd::desktop::file_chooser::{OpenFileRequest, SaveFileRequest};
use async_task::Runnable;
use flume::{Receiver, Sender};
use futures::channel::oneshot;
@ -214,7 +215,7 @@ impl Platform for LinuxPlatform {
}
fn open_url(&self, url: &str) {
unimplemented!()
open::that(url);
}
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
@ -225,15 +226,75 @@ impl Platform for LinuxPlatform {
&self,
options: PathPromptOptions,
) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
unimplemented!()
let (done_tx, done_rx) = oneshot::channel();
self.foreground_executor()
.spawn(async move {
let title = if options.multiple {
if !options.files {
"Open folders"
} else {
"Open files"
}
} else {
if !options.files {
"Open folder"
} else {
"Open file"
}
};
let result = OpenFileRequest::default()
.modal(true)
.title(title)
.accept_label("Select")
.multiple(options.multiple)
.directory(options.directories)
.send()
.await
.ok()
.and_then(|request| request.response().ok())
.and_then(|response| {
response
.uris()
.iter()
.map(|uri| uri.to_file_path().ok())
.collect()
});
done_tx.send(result);
})
.detach();
done_rx
}
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
unimplemented!()
let (done_tx, done_rx) = oneshot::channel();
let directory = directory.to_owned();
self.foreground_executor()
.spawn(async move {
let result = SaveFileRequest::default()
.modal(true)
.title("Select new path")
.accept_label("Accept")
.send()
.await
.ok()
.and_then(|request| request.response().ok())
.and_then(|response| {
response
.uris()
.first()
.and_then(|uri| uri.to_file_path().ok())
});
done_tx.send(result);
})
.detach();
done_rx
}
fn reveal_path(&self, path: &Path) {
unimplemented!()
open::that(path);
}
fn on_become_active(&self, callback: Box<dyn FnMut()>) {