@@ -43,6 +43,50 @@ pub(crate) const KEYRING_LABEL: &str = "zed-github-account";
const FILE_PICKER_PORTAL_MISSING: &str =
"Couldn't open file picker due to missing xdg-desktop-portal implementation.";
+#[cfg(any(feature = "x11", feature = "wayland"))]
+pub trait ResultExt {
+ type Ok;
+
+ fn notify_err(self, msg: &'static str) -> Self::Ok;
+}
+
+#[cfg(any(feature = "x11", feature = "wayland"))]
+impl<T> ResultExt for anyhow::Result<T> {
+ type Ok = T;
+
+ fn notify_err(self, msg: &'static str) -> T {
+ match self {
+ Ok(v) => v,
+ Err(e) => {
+ use ashpd::desktop::notification::{Notification, NotificationProxy, Priority};
+ use futures::executor::block_on;
+
+ let proxy = block_on(NotificationProxy::new()).expect(msg);
+
+ let notification_id = "dev.zed.Oops";
+ block_on(
+ proxy.add_notification(
+ notification_id,
+ Notification::new("Zed failed to launch")
+ .body(Some(
+ format!(
+ "{e:?}. See https://zed.dev/docs/linux for troubleshooting steps."
+ )
+ .as_str(),
+ ))
+ .priority(Priority::High)
+ .icon(ashpd::desktop::Icon::with_names(&[
+ "dialog-question-symbolic",
+ ])),
+ )
+ ).expect(msg);
+
+ panic!("{msg}");
+ }
+ }
+ }
+}
+
pub trait LinuxClient {
fn compositor_name(&self) -> &'static str;
fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R;
@@ -17,7 +17,7 @@ use collections::HashMap;
use filedescriptor::Pipe;
use http_client::Url;
use smallvec::SmallVec;
-use util::ResultExt;
+use util::ResultExt as _;
use wayland_backend::client::ObjectId;
use wayland_backend::protocol::WEnum;
use wayland_client::event_created_child;
@@ -76,8 +76,8 @@ use crate::{
FileDropEvent, ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon,
LinuxKeyboardLayout, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay,
- PlatformInput, PlatformKeyboardLayout, Point, SCROLL_LINES, ScrollDelta, ScrollWheelEvent,
- Size, TouchPhase, WindowParams, point, px, size,
+ PlatformInput, PlatformKeyboardLayout, Point, ResultExt as _, SCROLL_LINES, ScrollDelta,
+ ScrollWheelEvent, Size, TouchPhase, WindowParams, point, px, size,
};
use crate::{
LinuxDispatcher, RunnableVariant, TaskTiming,
@@ -531,7 +531,8 @@ impl WaylandClient {
})
.unwrap();
- let gpu_context = BladeContext::new().expect("Unable to init GPU context");
+ // This could be unified with the notification handling in zed/main:fail_to_open_window.
+ let gpu_context = BladeContext::new().notify_err("Unable to init GPU context");
let seat = seat.unwrap();
let globals = Globals::new(
@@ -1,4 +1,4 @@
-use crate::{Capslock, LinuxDispatcher, RunnableVariant, TaskTiming, xcb_flush};
+use crate::{Capslock, LinuxDispatcher, ResultExt as _, RunnableVariant, TaskTiming, xcb_flush};
use anyhow::{Context as _, anyhow};
use ashpd::WindowIdentifier;
use calloop::{
@@ -18,7 +18,7 @@ use std::{
rc::{Rc, Weak},
time::{Duration, Instant},
};
-use util::ResultExt;
+use util::ResultExt as _;
use x11rb::{
connection::{Connection, RequestConnection},
@@ -437,7 +437,7 @@ impl X11Client {
.to_string();
let keyboard_layout = LinuxKeyboardLayout::new(layout_name.into());
- let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
+ let gpu_context = BladeContext::new().notify_err("Unable to init GPU context");
let resource_database = x11rb::resource_manager::new_from_default(&xcb_connection)
.context("Failed to create resource database")?;
@@ -130,6 +130,7 @@ fn fail_to_open_window(e: anyhow::Error, _cx: &mut App) {
process::exit(1);
}
+ // Maybe unify this with gpui::platform::linux::platform::ResultExt::notify_err(..)?
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
{
use ashpd::desktop::notification::{Notification, NotificationProxy, Priority};