From a245660533fb5c5b602f6ee2b0759ef7895d5ebc Mon Sep 17 00:00:00 2001 From: Taha Date: Wed, 18 Mar 2026 08:11:19 -0700 Subject: [PATCH] gpui_linux: Fix "No Apps Available" dialog when opening URIs on Linux/Wayland (#49752) Closes #48169 Before you mark this PR as ready for review, make sure that you have: - [ ] Added a solid test coverage and/or screenshots from doing manual testing - [x] Done a self-review taking into account security and performance aspects - [ ] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Fixed "No Apps Available" dialog when opening URIs on Linux/Wayland Swaps the order of `open_uri_internal` function: try xdg-open first, and only fall back to the portal if every candidate command fails. Build Tests: I tested the build on Arch Linux & MacOS Tahoe and there were no issues. No error logs when opening repo links. --- crates/gpui_linux/src/linux/platform.rs | 42 ++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/crates/gpui_linux/src/linux/platform.rs b/crates/gpui_linux/src/linux/platform.rs index 4cd89f35d1e757ca30acd33b1362d147a95b63ef..cb46fa028727a24a481f2ca275368af0cf841e93 100644 --- a/crates/gpui_linux/src/linux/platform.rs +++ b/crates/gpui_linux/src/linux/platform.rs @@ -633,28 +633,42 @@ pub(super) fn open_uri_internal( if let Some(uri) = ashpd::Uri::parse(uri).log_err() { executor .spawn(async move { - match ashpd::desktop::open_uri::OpenFileRequest::default() - .activation_token(activation_token.clone().map(ashpd::ActivationToken::from)) - .send_uri(&uri) - .await - .and_then(|e| e.response()) - { - Ok(()) => return, - Err(e) => log::error!("Failed to open with dbus: {}", e), - } - + let mut xdg_open_failed = false; for mut command in open::commands(uri.to_string()) { if let Some(token) = activation_token.as_ref() { command.env("XDG_ACTIVATION_TOKEN", token); } let program = format!("{:?}", command.get_program()); match smol::process::Command::from(command).spawn() { - Ok(mut cmd) => { - cmd.status().await.log_err(); - return; + Ok(mut cmd) => match cmd.status().await { + Ok(status) if status.success() => return, + Ok(status) => { + log::error!("Command {} exited with status: {}", program, status); + xdg_open_failed = true; + } + Err(e) => { + log::error!("Failed to get status from {}: {}", program, e); + xdg_open_failed = true; + } + }, + Err(e) => { + log::error!("Failed to open with {}: {}", program, e); + xdg_open_failed = true; } + } + } + + if xdg_open_failed { + match ashpd::desktop::open_uri::OpenFileRequest::default() + .activation_token(activation_token.map(ashpd::ActivationToken::from)) + .send_uri(&uri) + .await + .and_then(|e| e.response()) + { + Ok(()) => {} + Err(ashpd::Error::Response(ashpd::desktop::ResponseError::Cancelled)) => {} Err(e) => { - log::error!("Failed to open with {}: {}", program, e) + log::error!("Failed to open with dbus: {}", e); } } }